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" 18*3c9a918cSPavel 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 26*3c9a918cSPavel Labath namespace { 27*3c9a918cSPavel Labath struct DwarfConstant { 28*3c9a918cSPavel Labath StringRef (*StringFn)(unsigned); 29*3c9a918cSPavel Labath StringRef Type; 30*3c9a918cSPavel Labath unsigned Value; 31*3c9a918cSPavel Labath }; 32*3c9a918cSPavel Labath 33*3c9a918cSPavel Labath static raw_ostream &operator<<(raw_ostream &OS, const DwarfConstant &C) { 34*3c9a918cSPavel Labath StringRef Str = C.StringFn(C.Value); 35*3c9a918cSPavel Labath if (!Str.empty()) 36*3c9a918cSPavel Labath return OS << Str; 37*3c9a918cSPavel Labath return OS << "DW_" << C.Type << "_Unknown_0x" << format("%x", C.Value); 38*3c9a918cSPavel Labath } 39*3c9a918cSPavel Labath } // namespace 40*3c9a918cSPavel Labath 41*3c9a918cSPavel Labath static DwarfConstant formatTag(unsigned Tag) { 42*3c9a918cSPavel Labath return {dwarf::TagString, "TAG", Tag}; 43*3c9a918cSPavel Labath } 44*3c9a918cSPavel Labath 45*3c9a918cSPavel Labath static DwarfConstant formatForm(unsigned Form) { 46*3c9a918cSPavel Labath return {dwarf::FormEncodingString, "FORM", Form}; 47*3c9a918cSPavel Labath } 48*3c9a918cSPavel Labath 49*3c9a918cSPavel Labath static DwarfConstant formatIndex(unsigned Idx) { 50*3c9a918cSPavel Labath return {dwarf::IndexString, "IDX", Idx}; 51*3c9a918cSPavel Labath } 52*3c9a918cSPavel Labath 53*3c9a918cSPavel Labath static DwarfConstant formatAtom(unsigned Atom) { 54*3c9a918cSPavel Labath return {dwarf::AtomTypeString, "ATOM", Atom}; 55*3c9a918cSPavel Labath } 56*3c9a918cSPavel Labath 57*3c9a918cSPavel Labath DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; 58*3c9a918cSPavel 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); 7082af9438SZachary Turner Hdr.NumBuckets = AccelSection.getU32(&Offset); 7182af9438SZachary Turner Hdr.NumHashes = 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 + 79ba915897SJonas Devlieghere Hdr.NumBuckets * 4 + Hdr.NumHashes * 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 979b36fd25SPavel Labath uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; } 989b36fd25SPavel Labath uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.NumHashes; } 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 1529b36fd25SPavel Labath LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const { 15399fdb9d9SAdrian Prantl if (!IsValid) 15499fdb9d9SAdrian Prantl return; 15599fdb9d9SAdrian Prantl 15682af9438SZachary Turner // Dump the header. 15782af9438SZachary Turner OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n' 15882af9438SZachary Turner << "Version = " << format("0x%04x", Hdr.Version) << '\n' 15982af9438SZachary Turner << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n' 16082af9438SZachary Turner << "Bucket count = " << Hdr.NumBuckets << '\n' 16182af9438SZachary Turner << "Hashes count = " << Hdr.NumHashes << '\n' 16282af9438SZachary Turner << "HeaderData length = " << Hdr.HeaderDataLength << '\n' 16382af9438SZachary Turner << "DIE offset base = " << HdrData.DIEOffsetBase << '\n' 16482af9438SZachary Turner << "Number of atoms = " << HdrData.Atoms.size() << '\n'; 16582af9438SZachary Turner 16682af9438SZachary Turner unsigned i = 0; 16782af9438SZachary Turner SmallVector<DWARFFormValue, 3> AtomForms; 16882af9438SZachary Turner for (const auto &Atom: HdrData.Atoms) { 169*3c9a918cSPavel Labath OS << format("Atom[%d] Type: ", i++) << formatAtom(Atom.first) 170*3c9a918cSPavel Labath << " Form: " << formatForm(Atom.second) << '\n'; 17182af9438SZachary Turner AtomForms.push_back(DWARFFormValue(Atom.second)); 17282af9438SZachary Turner } 17382af9438SZachary Turner 17482af9438SZachary Turner // Now go through the actual tables and dump them. 17582af9438SZachary Turner uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; 17682af9438SZachary Turner unsigned HashesBase = Offset + Hdr.NumBuckets * 4; 17782af9438SZachary Turner unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; 178e5400f8aSPaul Robinson DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; 17982af9438SZachary Turner 18082af9438SZachary Turner for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) { 18182af9438SZachary Turner unsigned Index = AccelSection.getU32(&Offset); 18282af9438SZachary Turner 18382af9438SZachary Turner OS << format("Bucket[%d]\n", Bucket); 18482af9438SZachary Turner if (Index == UINT32_MAX) { 18582af9438SZachary Turner OS << " EMPTY\n"; 18682af9438SZachary Turner continue; 18782af9438SZachary Turner } 18882af9438SZachary Turner 18982af9438SZachary Turner for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) { 19082af9438SZachary Turner unsigned HashOffset = HashesBase + HashIdx*4; 19182af9438SZachary Turner unsigned OffsetsOffset = OffsetsBase + HashIdx*4; 19282af9438SZachary Turner uint32_t Hash = AccelSection.getU32(&HashOffset); 19382af9438SZachary Turner 19482af9438SZachary Turner if (Hash % Hdr.NumBuckets != Bucket) 19582af9438SZachary Turner break; 19682af9438SZachary Turner 19782af9438SZachary Turner unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); 19882af9438SZachary Turner OS << format(" Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset); 19982af9438SZachary Turner if (!AccelSection.isValidOffset(DataOffset)) { 20082af9438SZachary Turner OS << " Invalid section offset\n"; 20182af9438SZachary Turner continue; 20282af9438SZachary Turner } 20382af9438SZachary Turner while (AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { 20417536b93SPaul Robinson unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); 20582af9438SZachary Turner if (!StringOffset) 20682af9438SZachary Turner break; 20782af9438SZachary Turner OS << format(" Name: %08x \"%s\"\n", StringOffset, 20882af9438SZachary Turner StringSection.getCStr(&StringOffset)); 20982af9438SZachary Turner unsigned NumData = AccelSection.getU32(&DataOffset); 21082af9438SZachary Turner for (unsigned Data = 0; Data < NumData; ++Data) { 21182af9438SZachary Turner OS << format(" Data[%d] => ", Data); 21282af9438SZachary Turner unsigned i = 0; 21382af9438SZachary Turner for (auto &Atom : AtomForms) { 21482af9438SZachary Turner OS << format("{Atom[%d]: ", i++); 215e5400f8aSPaul Robinson if (Atom.extractValue(AccelSection, &DataOffset, FormParams)) 216cddab279SGreg Clayton Atom.dump(OS); 21782af9438SZachary Turner else 21882af9438SZachary Turner OS << "Error extracting the value"; 21982af9438SZachary Turner OS << "} "; 22082af9438SZachary Turner } 22182af9438SZachary Turner OS << '\n'; 22282af9438SZachary Turner } 22382af9438SZachary Turner } 22482af9438SZachary Turner } 22582af9438SZachary Turner } 22682af9438SZachary Turner } 22799fdb9d9SAdrian Prantl 2289b36fd25SPavel Labath AppleAcceleratorTable::ValueIterator::ValueIterator( 2299b36fd25SPavel Labath const AppleAcceleratorTable &AccelTable, unsigned Offset) 23099fdb9d9SAdrian Prantl : AccelTable(&AccelTable), DataOffset(Offset) { 23199fdb9d9SAdrian Prantl if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) 23299fdb9d9SAdrian Prantl return; 23399fdb9d9SAdrian Prantl 23499fdb9d9SAdrian Prantl for (const auto &Atom : AccelTable.HdrData.Atoms) 23599fdb9d9SAdrian Prantl AtomForms.push_back(DWARFFormValue(Atom.second)); 23699fdb9d9SAdrian Prantl 23799fdb9d9SAdrian Prantl // Read the first entry. 23899fdb9d9SAdrian Prantl NumData = AccelTable.AccelSection.getU32(&DataOffset); 23999fdb9d9SAdrian Prantl Next(); 24099fdb9d9SAdrian Prantl } 24199fdb9d9SAdrian Prantl 2429b36fd25SPavel Labath void AppleAcceleratorTable::ValueIterator::Next() { 24399fdb9d9SAdrian Prantl assert(NumData > 0 && "attempted to increment iterator past the end"); 24499fdb9d9SAdrian Prantl auto &AccelSection = AccelTable->AccelSection; 24599fdb9d9SAdrian Prantl if (Data >= NumData || 24699fdb9d9SAdrian Prantl !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { 24799fdb9d9SAdrian Prantl NumData = 0; 24899fdb9d9SAdrian Prantl return; 24999fdb9d9SAdrian Prantl } 250e5400f8aSPaul Robinson DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0, 251e5400f8aSPaul Robinson dwarf::DwarfFormat::DWARF32}; 25299fdb9d9SAdrian Prantl for (auto &Atom : AtomForms) 253e5400f8aSPaul Robinson Atom.extractValue(AccelSection, &DataOffset, FormParams); 25499fdb9d9SAdrian Prantl ++Data; 25599fdb9d9SAdrian Prantl } 25699fdb9d9SAdrian Prantl 2579b36fd25SPavel Labath iterator_range<AppleAcceleratorTable::ValueIterator> 2589b36fd25SPavel Labath AppleAcceleratorTable::equal_range(StringRef Key) const { 25999fdb9d9SAdrian Prantl if (!IsValid) 26099fdb9d9SAdrian Prantl return make_range(ValueIterator(), ValueIterator()); 26199fdb9d9SAdrian Prantl 26299fdb9d9SAdrian Prantl // Find the bucket. 26392ac9d3eSJonas Devlieghere unsigned HashValue = djbHash(Key); 26499fdb9d9SAdrian Prantl unsigned Bucket = HashValue % Hdr.NumBuckets; 26599fdb9d9SAdrian Prantl unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength; 26699fdb9d9SAdrian Prantl unsigned HashesBase = BucketBase + Hdr.NumBuckets * 4; 26799fdb9d9SAdrian Prantl unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; 26899fdb9d9SAdrian Prantl 26999fdb9d9SAdrian Prantl unsigned BucketOffset = BucketBase + Bucket * 4; 27099fdb9d9SAdrian Prantl unsigned Index = AccelSection.getU32(&BucketOffset); 27199fdb9d9SAdrian Prantl 27299fdb9d9SAdrian Prantl // Search through all hashes in the bucket. 27399fdb9d9SAdrian Prantl for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) { 27499fdb9d9SAdrian Prantl unsigned HashOffset = HashesBase + HashIdx * 4; 27599fdb9d9SAdrian Prantl unsigned OffsetsOffset = OffsetsBase + HashIdx * 4; 27699fdb9d9SAdrian Prantl uint32_t Hash = AccelSection.getU32(&HashOffset); 27799fdb9d9SAdrian Prantl 27899fdb9d9SAdrian Prantl if (Hash % Hdr.NumBuckets != Bucket) 27999fdb9d9SAdrian Prantl // We are already in the next bucket. 28099fdb9d9SAdrian Prantl break; 28199fdb9d9SAdrian Prantl 28299fdb9d9SAdrian Prantl unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); 28399fdb9d9SAdrian Prantl unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); 28499fdb9d9SAdrian Prantl if (!StringOffset) 28599fdb9d9SAdrian Prantl break; 28699fdb9d9SAdrian Prantl 28799fdb9d9SAdrian Prantl // Finally, compare the key. 28899fdb9d9SAdrian Prantl if (Key == StringSection.getCStr(&StringOffset)) 28999fdb9d9SAdrian Prantl return make_range({*this, DataOffset}, ValueIterator()); 29099fdb9d9SAdrian Prantl } 29199fdb9d9SAdrian Prantl return make_range(ValueIterator(), ValueIterator()); 29299fdb9d9SAdrian Prantl } 293*3c9a918cSPavel Labath 294*3c9a918cSPavel Labath void DWARFDebugNames::Header::dump(ScopedPrinter &W) const { 295*3c9a918cSPavel Labath DictScope HeaderScope(W, "Header"); 296*3c9a918cSPavel Labath W.printHex("Length", UnitLength); 297*3c9a918cSPavel Labath W.printNumber("Version", Version); 298*3c9a918cSPavel Labath W.printHex("Padding", Padding); 299*3c9a918cSPavel Labath W.printNumber("CU count", CompUnitCount); 300*3c9a918cSPavel Labath W.printNumber("Local TU count", LocalTypeUnitCount); 301*3c9a918cSPavel Labath W.printNumber("Foreign TU count", ForeignTypeUnitCount); 302*3c9a918cSPavel Labath W.printNumber("Bucket count", BucketCount); 303*3c9a918cSPavel Labath W.printNumber("Name count", NameCount); 304*3c9a918cSPavel Labath W.printHex("Abbreviations table size", AbbrevTableSize); 305*3c9a918cSPavel Labath W.startLine() << "Augmentation: '" << AugmentationString << "'\n"; 306*3c9a918cSPavel Labath } 307*3c9a918cSPavel Labath 308*3c9a918cSPavel Labath llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, 309*3c9a918cSPavel Labath uint32_t *Offset) { 310*3c9a918cSPavel Labath // Check that we can read the fixed-size part. 311*3c9a918cSPavel Labath if (!AS.isValidOffset(*Offset + sizeof(Header) - 1)) 312*3c9a918cSPavel Labath return make_error<StringError>("Section too small: cannot read header.", 313*3c9a918cSPavel Labath inconvertibleErrorCode()); 314*3c9a918cSPavel Labath 315*3c9a918cSPavel Labath UnitLength = AS.getU32(Offset); 316*3c9a918cSPavel Labath Version = AS.getU16(Offset); 317*3c9a918cSPavel Labath Padding = AS.getU16(Offset); 318*3c9a918cSPavel Labath CompUnitCount = AS.getU32(Offset); 319*3c9a918cSPavel Labath LocalTypeUnitCount = AS.getU32(Offset); 320*3c9a918cSPavel Labath ForeignTypeUnitCount = AS.getU32(Offset); 321*3c9a918cSPavel Labath BucketCount = AS.getU32(Offset); 322*3c9a918cSPavel Labath NameCount = AS.getU32(Offset); 323*3c9a918cSPavel Labath AbbrevTableSize = AS.getU32(Offset); 324*3c9a918cSPavel Labath AugmentationStringSize = AS.getU32(Offset); 325*3c9a918cSPavel Labath 326*3c9a918cSPavel Labath if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize)) 327*3c9a918cSPavel Labath return make_error<StringError>( 328*3c9a918cSPavel Labath "Section too small: cannot read header augmentation.", 329*3c9a918cSPavel Labath inconvertibleErrorCode()); 330*3c9a918cSPavel Labath AugmentationString.resize(AugmentationStringSize); 331*3c9a918cSPavel Labath AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()), 332*3c9a918cSPavel Labath AugmentationStringSize); 333*3c9a918cSPavel Labath *Offset = alignTo(*Offset, 4); 334*3c9a918cSPavel Labath return Error::success(); 335*3c9a918cSPavel Labath } 336*3c9a918cSPavel Labath 337*3c9a918cSPavel Labath void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { 338*3c9a918cSPavel Labath DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str()); 339*3c9a918cSPavel Labath W.startLine() << "Tag: " << formatTag(Tag) << '\n'; 340*3c9a918cSPavel Labath 341*3c9a918cSPavel Labath for (const auto &Attr : Attributes) { 342*3c9a918cSPavel Labath W.startLine() << formatIndex(Attr.Index) << ": " << formatForm(Attr.Form) 343*3c9a918cSPavel Labath << '\n'; 344*3c9a918cSPavel Labath } 345*3c9a918cSPavel Labath } 346*3c9a918cSPavel Labath 347*3c9a918cSPavel Labath static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() { 348*3c9a918cSPavel Labath return {dwarf::Index(0), dwarf::Form(0)}; 349*3c9a918cSPavel Labath } 350*3c9a918cSPavel Labath 351*3c9a918cSPavel Labath static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE) { 352*3c9a918cSPavel Labath return AE == sentinelAttrEnc(); 353*3c9a918cSPavel Labath } 354*3c9a918cSPavel Labath 355*3c9a918cSPavel Labath static DWARFDebugNames::Abbrev sentinelAbbrev() { 356*3c9a918cSPavel Labath return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), {}); 357*3c9a918cSPavel Labath } 358*3c9a918cSPavel Labath 359*3c9a918cSPavel Labath static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) { 360*3c9a918cSPavel Labath return Abbr.Code == 0; 361*3c9a918cSPavel Labath } 362*3c9a918cSPavel Labath 363*3c9a918cSPavel Labath DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() { 364*3c9a918cSPavel Labath return sentinelAbbrev(); 365*3c9a918cSPavel Labath } 366*3c9a918cSPavel Labath 367*3c9a918cSPavel Labath DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { 368*3c9a918cSPavel Labath return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {}); 369*3c9a918cSPavel Labath } 370*3c9a918cSPavel Labath 371*3c9a918cSPavel Labath Expected<DWARFDebugNames::AttributeEncoding> 372*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) { 373*3c9a918cSPavel Labath if (*Offset >= EntriesBase) { 374*3c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated abbreviation table.", 375*3c9a918cSPavel Labath inconvertibleErrorCode()); 376*3c9a918cSPavel Labath } 377*3c9a918cSPavel Labath 378*3c9a918cSPavel Labath uint32_t Index = Section.AccelSection.getULEB128(Offset); 379*3c9a918cSPavel Labath uint32_t Form = Section.AccelSection.getULEB128(Offset); 380*3c9a918cSPavel Labath return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form)); 381*3c9a918cSPavel Labath } 382*3c9a918cSPavel Labath 383*3c9a918cSPavel Labath Expected<std::vector<DWARFDebugNames::AttributeEncoding>> 384*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) { 385*3c9a918cSPavel Labath std::vector<AttributeEncoding> Result; 386*3c9a918cSPavel Labath for (;;) { 387*3c9a918cSPavel Labath auto AttrEncOr = extractAttributeEncoding(Offset); 388*3c9a918cSPavel Labath if (!AttrEncOr) 389*3c9a918cSPavel Labath return AttrEncOr.takeError(); 390*3c9a918cSPavel Labath if (isSentinel(*AttrEncOr)) 391*3c9a918cSPavel Labath return std::move(Result); 392*3c9a918cSPavel Labath 393*3c9a918cSPavel Labath Result.emplace_back(*AttrEncOr); 394*3c9a918cSPavel Labath } 395*3c9a918cSPavel Labath } 396*3c9a918cSPavel Labath 397*3c9a918cSPavel Labath Expected<DWARFDebugNames::Abbrev> 398*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) { 399*3c9a918cSPavel Labath if (*Offset >= EntriesBase) { 400*3c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated abbreviation table.", 401*3c9a918cSPavel Labath inconvertibleErrorCode()); 402*3c9a918cSPavel Labath } 403*3c9a918cSPavel Labath 404*3c9a918cSPavel Labath uint32_t Code = Section.AccelSection.getULEB128(Offset); 405*3c9a918cSPavel Labath if (Code == 0) 406*3c9a918cSPavel Labath return sentinelAbbrev(); 407*3c9a918cSPavel Labath 408*3c9a918cSPavel Labath uint32_t Tag = Section.AccelSection.getULEB128(Offset); 409*3c9a918cSPavel Labath auto AttrEncOr = extractAttributeEncodings(Offset); 410*3c9a918cSPavel Labath if (!AttrEncOr) 411*3c9a918cSPavel Labath return AttrEncOr.takeError(); 412*3c9a918cSPavel Labath return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr)); 413*3c9a918cSPavel Labath } 414*3c9a918cSPavel Labath 415*3c9a918cSPavel Labath Error DWARFDebugNames::NameIndex::extract() { 416*3c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 417*3c9a918cSPavel Labath uint32_t Offset = Base; 418*3c9a918cSPavel Labath if (Error E = Hdr.extract(AS, &Offset)) 419*3c9a918cSPavel Labath return E; 420*3c9a918cSPavel Labath 421*3c9a918cSPavel Labath CUsBase = Offset; 422*3c9a918cSPavel Labath Offset += Hdr.CompUnitCount * 4; 423*3c9a918cSPavel Labath Offset += Hdr.LocalTypeUnitCount * 4; 424*3c9a918cSPavel Labath Offset += Hdr.ForeignTypeUnitCount * 8; 425*3c9a918cSPavel Labath BucketsBase = Offset; 426*3c9a918cSPavel Labath Offset += Hdr.BucketCount * 4; 427*3c9a918cSPavel Labath HashesBase = Offset; 428*3c9a918cSPavel Labath if (Hdr.BucketCount > 0) 429*3c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 430*3c9a918cSPavel Labath StringOffsetsBase = Offset; 431*3c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 432*3c9a918cSPavel Labath EntryOffsetsBase = Offset; 433*3c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 434*3c9a918cSPavel Labath 435*3c9a918cSPavel Labath if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize)) 436*3c9a918cSPavel Labath return make_error<StringError>( 437*3c9a918cSPavel Labath "Section too small: cannot read abbreviations.", 438*3c9a918cSPavel Labath inconvertibleErrorCode()); 439*3c9a918cSPavel Labath 440*3c9a918cSPavel Labath EntriesBase = Offset + Hdr.AbbrevTableSize; 441*3c9a918cSPavel Labath 442*3c9a918cSPavel Labath for (;;) { 443*3c9a918cSPavel Labath auto AbbrevOr = extractAbbrev(&Offset); 444*3c9a918cSPavel Labath if (!AbbrevOr) 445*3c9a918cSPavel Labath return AbbrevOr.takeError(); 446*3c9a918cSPavel Labath if (isSentinel(*AbbrevOr)) 447*3c9a918cSPavel Labath return Error::success(); 448*3c9a918cSPavel Labath 449*3c9a918cSPavel Labath if (!Abbrevs.insert(std::move(*AbbrevOr)).second) { 450*3c9a918cSPavel Labath return make_error<StringError>("Duplicate abbreviation code.", 451*3c9a918cSPavel Labath inconvertibleErrorCode()); 452*3c9a918cSPavel Labath } 453*3c9a918cSPavel Labath } 454*3c9a918cSPavel Labath } 455*3c9a918cSPavel Labath 456*3c9a918cSPavel Labath DWARFDebugNames::Entry::Entry(const Abbrev &Abbr) : Abbr(Abbr) { 457*3c9a918cSPavel Labath // This merely creates form values. It is up to the caller 458*3c9a918cSPavel Labath // (NameIndex::getEntry) to populate them. 459*3c9a918cSPavel Labath Values.reserve(Abbr.Attributes.size()); 460*3c9a918cSPavel Labath for (const auto &Attr : Abbr.Attributes) 461*3c9a918cSPavel Labath Values.emplace_back(Attr.Form); 462*3c9a918cSPavel Labath } 463*3c9a918cSPavel Labath 464*3c9a918cSPavel Labath void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const { 465*3c9a918cSPavel Labath W.printHex("Abbrev", Abbr.Code); 466*3c9a918cSPavel Labath W.startLine() << "Tag: " << formatTag(Abbr.Tag) << "\n"; 467*3c9a918cSPavel Labath 468*3c9a918cSPavel Labath assert(Abbr.Attributes.size() == Values.size()); 469*3c9a918cSPavel Labath for (uint32_t I = 0, E = Values.size(); I < E; ++I) { 470*3c9a918cSPavel Labath W.startLine() << formatIndex(Abbr.Attributes[I].Index) << ": "; 471*3c9a918cSPavel Labath Values[I].dump(W.getOStream()); 472*3c9a918cSPavel Labath W.getOStream() << '\n'; 473*3c9a918cSPavel Labath } 474*3c9a918cSPavel Labath } 475*3c9a918cSPavel Labath 476*3c9a918cSPavel Labath char DWARFDebugNames::SentinelError::ID; 477*3c9a918cSPavel Labath std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const { 478*3c9a918cSPavel Labath return inconvertibleErrorCode(); 479*3c9a918cSPavel Labath } 480*3c9a918cSPavel Labath 481*3c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const { 482*3c9a918cSPavel Labath assert(CU < Hdr.CompUnitCount); 483*3c9a918cSPavel Labath uint32_t Offset = CUsBase + 4 * CU; 484*3c9a918cSPavel Labath return Section.AccelSection.getRelocatedValue(4, &Offset); 485*3c9a918cSPavel Labath } 486*3c9a918cSPavel Labath 487*3c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const { 488*3c9a918cSPavel Labath assert(TU < Hdr.LocalTypeUnitCount); 489*3c9a918cSPavel Labath uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4; 490*3c9a918cSPavel Labath return Section.AccelSection.getRelocatedValue(4, &Offset); 491*3c9a918cSPavel Labath } 492*3c9a918cSPavel Labath 493*3c9a918cSPavel Labath uint64_t DWARFDebugNames::NameIndex::getForeignTUOffset(uint32_t TU) const { 494*3c9a918cSPavel Labath assert(TU < Hdr.ForeignTypeUnitCount); 495*3c9a918cSPavel Labath uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4; 496*3c9a918cSPavel Labath return Section.AccelSection.getU64(&Offset); 497*3c9a918cSPavel Labath } 498*3c9a918cSPavel Labath 499*3c9a918cSPavel Labath Expected<DWARFDebugNames::Entry> 500*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { 501*3c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 502*3c9a918cSPavel Labath if (!AS.isValidOffset(*Offset)) 503*3c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated entry list", 504*3c9a918cSPavel Labath inconvertibleErrorCode()); 505*3c9a918cSPavel Labath 506*3c9a918cSPavel Labath uint32_t AbbrevCode = AS.getULEB128(Offset); 507*3c9a918cSPavel Labath if (AbbrevCode == 0) 508*3c9a918cSPavel Labath return make_error<SentinelError>(); 509*3c9a918cSPavel Labath 510*3c9a918cSPavel Labath const auto AbbrevIt = Abbrevs.find_as(AbbrevCode); 511*3c9a918cSPavel Labath if (AbbrevIt == Abbrevs.end()) 512*3c9a918cSPavel Labath return make_error<StringError>("Invalid abbreviation", 513*3c9a918cSPavel Labath inconvertibleErrorCode()); 514*3c9a918cSPavel Labath 515*3c9a918cSPavel Labath Entry E(*AbbrevIt); 516*3c9a918cSPavel Labath 517*3c9a918cSPavel Labath DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; 518*3c9a918cSPavel Labath for (auto &Value : E.Values) { 519*3c9a918cSPavel Labath if (!Value.extractValue(AS, Offset, FormParams)) 520*3c9a918cSPavel Labath return make_error<StringError>("Error extracting index attribute values", 521*3c9a918cSPavel Labath inconvertibleErrorCode()); 522*3c9a918cSPavel Labath } 523*3c9a918cSPavel Labath return std::move(E); 524*3c9a918cSPavel Labath } 525*3c9a918cSPavel Labath 526*3c9a918cSPavel Labath DWARFDebugNames::NameTableEntry 527*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const { 528*3c9a918cSPavel Labath assert(0 < Index && Index <= Hdr.NameCount); 529*3c9a918cSPavel Labath uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1); 530*3c9a918cSPavel Labath uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1); 531*3c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 532*3c9a918cSPavel Labath 533*3c9a918cSPavel Labath uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset); 534*3c9a918cSPavel Labath uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset); 535*3c9a918cSPavel Labath EntryOffset += EntriesBase; 536*3c9a918cSPavel Labath return {StringOffset, EntryOffset}; 537*3c9a918cSPavel Labath } 538*3c9a918cSPavel Labath 539*3c9a918cSPavel Labath uint32_t 540*3c9a918cSPavel Labath DWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const { 541*3c9a918cSPavel Labath assert(Bucket < Hdr.BucketCount); 542*3c9a918cSPavel Labath uint32_t BucketOffset = BucketsBase + 4 * Bucket; 543*3c9a918cSPavel Labath return Section.AccelSection.getU32(&BucketOffset); 544*3c9a918cSPavel Labath } 545*3c9a918cSPavel Labath 546*3c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const { 547*3c9a918cSPavel Labath assert(0 < Index && Index <= Hdr.NameCount); 548*3c9a918cSPavel Labath uint32_t HashOffset = HashesBase + 4 * (Index - 1); 549*3c9a918cSPavel Labath return Section.AccelSection.getU32(&HashOffset); 550*3c9a918cSPavel Labath } 551*3c9a918cSPavel Labath 552*3c9a918cSPavel Labath // Returns true if we should continue scanning for entries, false if this is the 553*3c9a918cSPavel Labath // last (sentinel) entry). In case of a parsing error we also return false, as 554*3c9a918cSPavel Labath // it's not possible to recover this entry list (but the other lists may still 555*3c9a918cSPavel Labath // parse OK). 556*3c9a918cSPavel Labath bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W, 557*3c9a918cSPavel Labath uint32_t *Offset) const { 558*3c9a918cSPavel Labath uint32_t EntryId = *Offset; 559*3c9a918cSPavel Labath auto EntryOr = getEntry(Offset); 560*3c9a918cSPavel Labath if (!EntryOr) { 561*3c9a918cSPavel Labath handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {}, 562*3c9a918cSPavel Labath [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); }); 563*3c9a918cSPavel Labath return false; 564*3c9a918cSPavel Labath } 565*3c9a918cSPavel Labath 566*3c9a918cSPavel Labath DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str()); 567*3c9a918cSPavel Labath EntryOr->dump(W); 568*3c9a918cSPavel Labath return true; 569*3c9a918cSPavel Labath } 570*3c9a918cSPavel Labath 571*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, uint32_t Index, 572*3c9a918cSPavel Labath Optional<uint32_t> Hash) const { 573*3c9a918cSPavel Labath const DataExtractor &SS = Section.StringSection; 574*3c9a918cSPavel Labath NameTableEntry NTE = getNameTableEntry(Index); 575*3c9a918cSPavel Labath 576*3c9a918cSPavel Labath DictScope NameScope(W, ("Name " + Twine(Index)).str()); 577*3c9a918cSPavel Labath if (Hash) 578*3c9a918cSPavel Labath W.printHex("Hash", *Hash); 579*3c9a918cSPavel Labath 580*3c9a918cSPavel Labath W.startLine() << format("String: 0x%08x", NTE.StringOffset); 581*3c9a918cSPavel Labath W.getOStream() << " \"" << SS.getCStr(&NTE.StringOffset) << "\"\n"; 582*3c9a918cSPavel Labath 583*3c9a918cSPavel Labath while (dumpEntry(W, &NTE.EntryOffset)) 584*3c9a918cSPavel Labath /*empty*/; 585*3c9a918cSPavel Labath } 586*3c9a918cSPavel Labath 587*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const { 588*3c9a918cSPavel Labath ListScope CUScope(W, "Compilation Unit offsets"); 589*3c9a918cSPavel Labath for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU) 590*3c9a918cSPavel Labath W.startLine() << format("CU[%u]: 0x%08x\n", CU, getCUOffset(CU)); 591*3c9a918cSPavel Labath } 592*3c9a918cSPavel Labath 593*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const { 594*3c9a918cSPavel Labath if (Hdr.LocalTypeUnitCount == 0) 595*3c9a918cSPavel Labath return; 596*3c9a918cSPavel Labath 597*3c9a918cSPavel Labath ListScope TUScope(W, "Local Type Unit offsets"); 598*3c9a918cSPavel Labath for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU) 599*3c9a918cSPavel Labath W.startLine() << format("LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU)); 600*3c9a918cSPavel Labath } 601*3c9a918cSPavel Labath 602*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const { 603*3c9a918cSPavel Labath if (Hdr.ForeignTypeUnitCount == 0) 604*3c9a918cSPavel Labath return; 605*3c9a918cSPavel Labath 606*3c9a918cSPavel Labath ListScope TUScope(W, "Foreign Type Unit signatures"); 607*3c9a918cSPavel Labath for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) { 608*3c9a918cSPavel Labath W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU, 609*3c9a918cSPavel Labath getForeignTUOffset(TU)); 610*3c9a918cSPavel Labath } 611*3c9a918cSPavel Labath } 612*3c9a918cSPavel Labath 613*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const { 614*3c9a918cSPavel Labath ListScope AbbrevsScope(W, "Abbreviations"); 615*3c9a918cSPavel Labath for (const auto &Abbr : Abbrevs) 616*3c9a918cSPavel Labath Abbr.dump(W); 617*3c9a918cSPavel Labath } 618*3c9a918cSPavel Labath 619*3c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W, 620*3c9a918cSPavel Labath uint32_t Bucket) const { 621*3c9a918cSPavel Labath ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str()); 622*3c9a918cSPavel Labath uint32_t Index = getBucketArrayEntry(Bucket); 623*3c9a918cSPavel Labath if (Index == 0) { 624*3c9a918cSPavel Labath W.printString("EMPTY"); 625*3c9a918cSPavel Labath return; 626*3c9a918cSPavel Labath } 627*3c9a918cSPavel Labath if (Index > Hdr.NameCount) { 628*3c9a918cSPavel Labath W.printString("Name index is invalid"); 629*3c9a918cSPavel Labath return; 630*3c9a918cSPavel Labath } 631*3c9a918cSPavel Labath 632*3c9a918cSPavel Labath for (; Index <= Hdr.NameCount; ++Index) { 633*3c9a918cSPavel Labath uint32_t Hash = getHashArrayEntry(Index); 634*3c9a918cSPavel Labath if (Hash % Hdr.BucketCount != Bucket) 635*3c9a918cSPavel Labath break; 636*3c9a918cSPavel Labath 637*3c9a918cSPavel Labath dumpName(W, Index, Hash); 638*3c9a918cSPavel Labath } 639*3c9a918cSPavel Labath } 640*3c9a918cSPavel Labath 641*3c9a918cSPavel Labath LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const { 642*3c9a918cSPavel Labath DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str()); 643*3c9a918cSPavel Labath Hdr.dump(W); 644*3c9a918cSPavel Labath dumpCUs(W); 645*3c9a918cSPavel Labath dumpLocalTUs(W); 646*3c9a918cSPavel Labath dumpForeignTUs(W); 647*3c9a918cSPavel Labath dumpAbbreviations(W); 648*3c9a918cSPavel Labath 649*3c9a918cSPavel Labath if (Hdr.BucketCount > 0) { 650*3c9a918cSPavel Labath for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) 651*3c9a918cSPavel Labath dumpBucket(W, Bucket); 652*3c9a918cSPavel Labath return; 653*3c9a918cSPavel Labath } 654*3c9a918cSPavel Labath 655*3c9a918cSPavel Labath W.startLine() << "Hash table not present\n"; 656*3c9a918cSPavel Labath for (uint32_t Index = 1; Index <= Hdr.NameCount; ++Index) 657*3c9a918cSPavel Labath dumpName(W, Index, None); 658*3c9a918cSPavel Labath } 659*3c9a918cSPavel Labath 660*3c9a918cSPavel Labath llvm::Error DWARFDebugNames::extract() { 661*3c9a918cSPavel Labath uint32_t Offset = 0; 662*3c9a918cSPavel Labath while (AccelSection.isValidOffset(Offset)) { 663*3c9a918cSPavel Labath NameIndex Next(*this, Offset); 664*3c9a918cSPavel Labath if (llvm::Error E = Next.extract()) 665*3c9a918cSPavel Labath return E; 666*3c9a918cSPavel Labath Offset = Next.getNextUnitOffset(); 667*3c9a918cSPavel Labath NameIndices.push_back(std::move(Next)); 668*3c9a918cSPavel Labath } 669*3c9a918cSPavel Labath return Error::success(); 670*3c9a918cSPavel Labath } 671*3c9a918cSPavel Labath 672*3c9a918cSPavel Labath LLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const { 673*3c9a918cSPavel Labath ScopedPrinter W(OS); 674*3c9a918cSPavel Labath for (const NameIndex &NI : NameIndices) 675*3c9a918cSPavel Labath NI.dump(W); 676*3c9a918cSPavel Labath } 677