LLVM 20.0.0git
DWARFAcceleratorTable.cpp
Go to the documentation of this file.
1//===- DWARFAcceleratorTable.cpp ------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
14#include "llvm/Support/DJB.h"
15#include "llvm/Support/Errc.h"
16#include "llvm/Support/Format.h"
20#include <cstddef>
21#include <cstdint>
22#include <utility>
23
24using namespace llvm;
25
26namespace {
27struct Atom {
28 unsigned Value;
29};
30
31static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
33 if (!Str.empty())
34 return OS << Str;
35 return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
36}
37} // namespace
38
39static Atom formatAtom(unsigned Atom) { return {Atom}; }
40
42
44 uint64_t Offset = 0;
45
46 // Check that we can at least read the header.
47 if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4))
49 "Section too small: cannot read header.");
50
51 Hdr.Magic = AccelSection.getU32(&Offset);
52 Hdr.Version = AccelSection.getU16(&Offset);
53 Hdr.HashFunction = AccelSection.getU16(&Offset);
54 Hdr.BucketCount = AccelSection.getU32(&Offset);
55 Hdr.HashCount = AccelSection.getU32(&Offset);
56 Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
57 FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
58
59 // Check that we can read all the hashes and offsets from the
60 // section (see SourceLevelDebugging.rst for the structure of the index).
61 if (!AccelSection.isValidOffset(getIthBucketBase(Hdr.BucketCount - 1)))
62 return createStringError(
64 "Section too small: cannot read buckets and hashes.");
65
66 HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
68
69 HashDataEntryLength = 0;
70 auto MakeUnsupportedFormError = [](dwarf::Form Form) {
72 "Unsupported form:" +
74 };
75
76 for (unsigned i = 0; i < NumAtoms; ++i) {
78 auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
79 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
80
81 std::optional<uint8_t> FormSize =
83 if (!FormSize)
84 return MakeUnsupportedFormError(AtomForm);
85 HashDataEntryLength += *FormSize;
86 }
87
88 IsValid = true;
89 return Error::success();
90}
91
93 return Hdr.BucketCount;
94}
95uint32_t AppleAcceleratorTable::getNumHashes() const { return Hdr.HashCount; }
96uint32_t AppleAcceleratorTable::getSizeHdr() const { return sizeof(Hdr); }
98 return Hdr.HeaderDataLength;
99}
100
104 return HdrData.Atoms;
105}
106
108 for (auto Atom : getAtomsDesc()) {
109 DWARFFormValue FormValue(Atom.second);
110 switch (Atom.first) {
114 if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
116 FormValue.getForm() == dwarf::DW_FORM_sdata)
117 return false;
118 break;
119 default:
120 break;
121 }
122 }
123 return true;
124}
125
126std::pair<uint64_t, dwarf::Tag>
129 dwarf::Tag DieTag = dwarf::DW_TAG_null;
130
131 for (auto Atom : getAtomsDesc()) {
132 DWARFFormValue FormValue(Atom.second);
133 FormValue.extractValue(AccelSection, HashDataOffset, FormParams);
134 switch (Atom.first) {
136 DieOffset = *FormValue.getAsUnsignedConstant();
137 break;
139 DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
140 break;
141 default:
142 break;
143 }
144 }
145 return {DieOffset, DieTag};
146}
147
148void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
149 DictScope HeaderScope(W, "Header");
150 W.printHex("Magic", Magic);
151 W.printHex("Version", Version);
152 W.printHex("Hash function", HashFunction);
153 W.printNumber("Bucket count", BucketCount);
154 W.printNumber("Hashes count", HashCount);
155 W.printNumber("HeaderData length", HeaderDataLength);
156}
157
158std::optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
159 std::optional<DWARFFormValue> Value) const {
160 if (!Value)
161 return std::nullopt;
162
163 switch (Value->getForm()) {
164 case dwarf::DW_FORM_ref1:
165 case dwarf::DW_FORM_ref2:
166 case dwarf::DW_FORM_ref4:
167 case dwarf::DW_FORM_ref8:
168 case dwarf::DW_FORM_ref_udata:
169 return Value->getRawUValue() + DIEOffsetBase;
170 default:
171 return Value->getAsSectionOffset();
172 }
173}
174
175bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
177 uint64_t *DataOffset) const {
178 uint64_t NameOffset = *DataOffset;
179 if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
180 W.printString("Incorrectly terminated list.");
181 return false;
182 }
183 uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
184 if (!StringOffset)
185 return false; // End of list
186
187 DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
188 W.startLine() << format("String: 0x%08" PRIx64, StringOffset);
189 W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";
190
191 unsigned NumData = AccelSection.getU32(DataOffset);
192 for (unsigned Data = 0; Data < NumData; ++Data) {
193 ListScope DataScope(W, ("Data " + Twine(Data)).str());
194 unsigned i = 0;
195 for (auto &Atom : AtomForms) {
196 W.startLine() << format("Atom[%d]: ", i);
197 if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
198 Atom.dump(W.getOStream());
199 if (std::optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
200 StringRef Str = dwarf::AtomValueString(HdrData.Atoms[i].first, *Val);
201 if (!Str.empty())
202 W.getOStream() << " (" << Str << ")";
203 }
204 } else
205 W.getOStream() << "Error extracting the value";
206 W.getOStream() << "\n";
207 i++;
208 }
209 }
210 return true; // more entries follow
211}
212
214 if (!IsValid)
215 return;
216
217 ScopedPrinter W(OS);
218
219 Hdr.dump(W);
220
221 W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
222 W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
223 W.printNumber("Size of each hash data entry", getHashDataEntryLength());
225 {
226 ListScope AtomsScope(W, "Atoms");
227 unsigned i = 0;
228 for (const auto &Atom : HdrData.Atoms) {
229 DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
230 W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
231 W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
232 AtomForms.push_back(DWARFFormValue(Atom.second));
233 }
234 }
235
236 // Now go through the actual tables and dump them.
237 uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
238 uint64_t HashesBase = Offset + Hdr.BucketCount * 4;
239 uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;
240
241 for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
242 unsigned Index = AccelSection.getU32(&Offset);
243
244 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
245 if (Index == UINT32_MAX) {
246 W.printString("EMPTY");
247 continue;
248 }
249
250 for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
251 uint64_t HashOffset = HashesBase + HashIdx*4;
252 uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
253 uint32_t Hash = AccelSection.getU32(&HashOffset);
254
255 if (Hash % Hdr.BucketCount != Bucket)
256 break;
257
258 uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset);
259 ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str());
260 if (!AccelSection.isValidOffset(DataOffset)) {
261 W.printString("Invalid section offset");
262 continue;
263 }
264 while (dumpName(W, AtomForms, &DataOffset))
265 /*empty*/;
266 }
267 }
268}
269
271 : Table(Table) {
272 Values.reserve(Table.HdrData.Atoms.size());
273 for (const auto &Atom : Table.HdrData.Atoms)
274 Values.push_back(DWARFFormValue(Atom.second));
275}
276
277void AppleAcceleratorTable::Entry::extract(uint64_t *Offset) {
278 for (auto &FormValue : Values)
279 FormValue.extractValue(Table.AccelSection, Offset, Table.FormParams);
280}
281
282std::optional<DWARFFormValue>
284 for (auto [Atom, FormValue] : zip_equal(Table.HdrData.Atoms, Values))
285 if (Atom.first == AtomToFind)
286 return FormValue;
287 return std::nullopt;
288}
289
290std::optional<uint64_t>
292 return Table.HdrData.extractOffset(lookup(dwarf::DW_ATOM_die_offset));
293}
294
295std::optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
296 return Table.HdrData.extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
297}
298
299std::optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
300 std::optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
301 if (!Tag)
302 return std::nullopt;
303 if (std::optional<uint64_t> Value = Tag->getAsUnsignedConstant())
304 return dwarf::Tag(*Value);
305 return std::nullopt;
306}
307
309 const AppleAcceleratorTable &AccelTable, uint64_t DataOffset)
310 : Current(AccelTable), Offset(DataOffset) {}
311
312void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() {
313 if (NumEntriesToCome == 0)
314 prepareNextStringOrEnd();
315 if (isEnd())
316 return;
317 uint64_t OffsetCopy = Offset;
318 Current.BaseEntry.extract(&OffsetCopy);
319 NumEntriesToCome--;
320 Offset += getTable().getHashDataEntryLength();
321}
322
323void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() {
324 std::optional<uint32_t> StrOffset = getTable().readStringOffsetAt(Offset);
325 if (!StrOffset)
326 return setToEnd();
327
328 // A zero denotes the end of the collision list. Read the next string
329 // again.
330 if (*StrOffset == 0)
331 return prepareNextStringOrEnd();
332 Current.StrOffset = *StrOffset;
333
334 std::optional<uint32_t> MaybeNumEntries = getTable().readU32FromAccel(Offset);
335 if (!MaybeNumEntries || *MaybeNumEntries == 0)
336 return setToEnd();
337 NumEntriesToCome = *MaybeNumEntries;
338}
339
341 bool SetEnd)
342 : Current(Table), Offset(Table.getEntriesBase()), NumEntriesToCome(0) {
343 if (SetEnd)
344 setToEnd();
345 else
346 prepareNextEntryOrEnd();
347}
348
351 const auto EmptyRange =
352 make_range(SameNameIterator(*this, 0), SameNameIterator(*this, 0));
353 if (!IsValid)
354 return EmptyRange;
355
356 // Find the bucket.
357 uint32_t SearchHash = djbHash(Key);
358 uint32_t BucketIdx = hashToBucketIdx(SearchHash);
359 std::optional<uint32_t> HashIdx = idxOfHashInBucket(SearchHash, BucketIdx);
360 if (!HashIdx)
361 return EmptyRange;
362
363 std::optional<uint64_t> MaybeDataOffset = readIthOffset(*HashIdx);
364 if (!MaybeDataOffset)
365 return EmptyRange;
366
367 uint64_t DataOffset = *MaybeDataOffset;
368 if (DataOffset >= AccelSection.size())
369 return EmptyRange;
370
371 std::optional<uint32_t> StrOffset = readStringOffsetAt(DataOffset);
372 // Valid input and still have strings in this hash.
373 while (StrOffset && *StrOffset) {
374 std::optional<StringRef> MaybeStr = readStringFromStrSection(*StrOffset);
375 std::optional<uint32_t> NumEntries = this->readU32FromAccel(DataOffset);
376 if (!MaybeStr || !NumEntries)
377 return EmptyRange;
378 uint64_t EndOffset = DataOffset + *NumEntries * getHashDataEntryLength();
379 if (Key == *MaybeStr)
380 return make_range({*this, DataOffset},
381 SameNameIterator{*this, EndOffset});
382 DataOffset = EndOffset;
383 StrOffset = readStringOffsetAt(DataOffset);
384 }
385
386 return EmptyRange;
387}
388
389std::optional<uint32_t>
390AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,
391 uint32_t BucketIdx) const {
392 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);
393 if (!HashStartIdx)
394 return std::nullopt;
395
396 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {
397 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);
398 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))
399 break;
400 if (*MaybeHash == HashToFind)
401 return HashIdx;
402 }
403 return std::nullopt;
404}
405
406std::optional<StringRef> AppleAcceleratorTable::readStringFromStrSection(
407 uint64_t StringSectionOffset) const {
408 Error E = Error::success();
409 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);
410 if (E) {
411 consumeError(std::move(E));
412 return std::nullopt;
413 }
414 return Str;
415}
416
417std::optional<uint32_t>
418AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,
419 bool UseRelocation) const {
420 Error E = Error::success();
421 uint32_t Data = UseRelocation
422 ? AccelSection.getRelocatedValue(4, &Offset, nullptr, &E)
423 : AccelSection.getU32(&Offset, &E);
424 if (E) {
425 consumeError(std::move(E));
426 return std::nullopt;
427 }
428 return Data;
429}
430
432 DictScope HeaderScope(W, "Header");
433 W.printHex("Length", UnitLength);
434 W.printString("Format", dwarf::FormatString(Format));
435 W.printNumber("Version", Version);
436 W.printNumber("CU count", CompUnitCount);
437 W.printNumber("Local TU count", LocalTypeUnitCount);
438 W.printNumber("Foreign TU count", ForeignTypeUnitCount);
439 W.printNumber("Bucket count", BucketCount);
440 W.printNumber("Name count", NameCount);
441 W.printHex("Abbreviations table size", AbbrevTableSize);
442 W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
443}
444
446 uint64_t *Offset) {
447 auto HeaderError = [Offset = *Offset](Error E) {
449 "parsing .debug_names header at 0x%" PRIx64 ": %s",
450 Offset, toString(std::move(E)).c_str());
451 };
452
454 std::tie(UnitLength, Format) = AS.getInitialLength(C);
455
456 Version = AS.getU16(C);
457 AS.skip(C, 2); // padding
458 CompUnitCount = AS.getU32(C);
459 LocalTypeUnitCount = AS.getU32(C);
460 ForeignTypeUnitCount = AS.getU32(C);
461 BucketCount = AS.getU32(C);
462 NameCount = AS.getU32(C);
463 AbbrevTableSize = AS.getU32(C);
464 AugmentationStringSize = alignTo(AS.getU32(C), 4);
465
466 if (!C)
467 return HeaderError(C.takeError());
468
469 if (!AS.isValidOffsetForDataOfSize(C.tell(), AugmentationStringSize))
471 "cannot read header augmentation"));
472 AugmentationString.resize(AugmentationStringSize);
473 AS.getU8(C, reinterpret_cast<uint8_t *>(AugmentationString.data()),
474 AugmentationStringSize);
475 *Offset = C.tell();
476 return C.takeError();
477}
478
480 DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
481 W.startLine() << formatv("Tag: {0}\n", Tag);
482
483 for (const auto &Attr : Attributes)
484 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
485}
486
488 return {dwarf::Index(0), dwarf::Form(0)};
489}
490
492 return AE == sentinelAttrEnc();
493}
494
496 return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), 0, {});
497}
498
499static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
500 return Abbr.Code == 0;
501}
502
503DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
504 return sentinelAbbrev();
505}
506
507DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
508 return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), 0, {});
509}
510
512DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
513 if (*Offset >= Offsets.EntriesBase) {
515 "Incorrectly terminated abbreviation table.");
516 }
517
518 uint32_t Index = Section.AccelSection.getULEB128(Offset);
519 uint32_t Form = Section.AccelSection.getULEB128(Offset);
520 return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
521}
522
524DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
525 std::vector<AttributeEncoding> Result;
526 for (;;) {
527 auto AttrEncOr = extractAttributeEncoding(Offset);
528 if (!AttrEncOr)
529 return AttrEncOr.takeError();
530 if (isSentinel(*AttrEncOr))
531 return std::move(Result);
532
533 Result.emplace_back(*AttrEncOr);
534 }
535}
536
538DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
539 if (*Offset >= Offsets.EntriesBase) {
541 "Incorrectly terminated abbreviation table.");
542 }
543 const uint64_t AbbrevOffset = *Offset;
544 uint32_t Code = Section.AccelSection.getULEB128(Offset);
545 if (Code == 0)
546 return sentinelAbbrev();
547
548 uint32_t Tag = Section.AccelSection.getULEB128(Offset);
549 auto AttrEncOr = extractAttributeEncodings(Offset);
550 if (!AttrEncOr)
551 return AttrEncOr.takeError();
552 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
553}
554
557 const DWARFDebugNames::Header &Hdr) {
558 uint64_t DwarfSize = getDwarfOffsetByteSize(Hdr.Format);
560 Ret.CUsBase = EndOfHeaderOffset;
561 Ret.BucketsBase = Ret.CUsBase + Hdr.CompUnitCount * DwarfSize +
562 Hdr.LocalTypeUnitCount * DwarfSize +
563 Hdr.ForeignTypeUnitCount * 8;
564 Ret.HashesBase = Ret.BucketsBase + Hdr.BucketCount * 4;
565 Ret.StringOffsetsBase =
566 Ret.HashesBase + (Hdr.BucketCount > 0 ? Hdr.NameCount * 4 : 0);
567 Ret.EntryOffsetsBase = Ret.StringOffsetsBase + Hdr.NameCount * DwarfSize;
568 Ret.EntriesBase =
569 Ret.EntryOffsetsBase + Hdr.NameCount * DwarfSize + Hdr.AbbrevTableSize;
570 return Ret;
571}
572
574 const DWARFDataExtractor &AS = Section.AccelSection;
575 uint64_t EndOfHeaderOffset = Base;
576 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
577 return E;
578
579 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
580 Offsets = dwarf::findDebugNamesOffsets(EndOfHeaderOffset, Hdr);
581
583 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
584
585 if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
587 "Section too small: cannot read abbreviations.");
588
589 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
590
591 for (;;) {
592 auto AbbrevOr = extractAbbrev(&Offset);
593 if (!AbbrevOr)
594 return AbbrevOr.takeError();
595 if (isSentinel(*AbbrevOr))
596 return Error::success();
597
598 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
600 "Duplicate abbreviation code.");
601 }
602}
603
604DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
605 : NameIdx(&NameIdx), Abbr(&Abbr) {
606 // This merely creates form values. It is up to the caller
607 // (NameIndex::getEntry) to populate them.
608 Values.reserve(Abbr.Attributes.size());
609 for (const auto &Attr : Abbr.Attributes)
610 Values.emplace_back(Attr.Form);
611}
612
613std::optional<DWARFFormValue>
615 assert(Abbr->Attributes.size() == Values.size());
616 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
617 if (std::get<0>(Tuple).Index == Index)
618 return std::get<1>(Tuple);
619 }
620 return std::nullopt;
621}
622
624 return lookup(dwarf::DW_IDX_parent).has_value();
625}
626
627std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
628 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
629 return Off->getAsReferenceUVal();
630 return std::nullopt;
631}
632
633std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
634 // Return the DW_IDX_compile_unit attribute value if it is specified.
635 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
636 return Off->getAsUnsignedConstant();
637 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
638 // implicitly refer to the single CU.
639 if (NameIdx->getCUCount() == 1)
640 return 0;
641 return std::nullopt;
642}
643
644std::optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
645 // Return the DW_IDX_compile_unit attribute value but only if we don't have a
646 // DW_IDX_type_unit attribute. Use Entry::getRelatedCUIndex() to get the
647 // associated CU index if this behaviour is not desired.
648 if (lookup(dwarf::DW_IDX_type_unit).has_value())
649 return std::nullopt;
650 return getRelatedCUIndex();
651}
652
653std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
654 std::optional<uint64_t> Index = getCUIndex();
655 if (!Index || *Index >= NameIdx->getCUCount())
656 return std::nullopt;
657 return NameIdx->getCUOffset(*Index);
658}
659
660std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
661 std::optional<uint64_t> Index = getRelatedCUIndex();
662 if (!Index || *Index >= NameIdx->getCUCount())
663 return std::nullopt;
664 return NameIdx->getCUOffset(*Index);
665}
666
667std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
668 std::optional<uint64_t> Index = getLocalTUIndex();
669 if (!Index || *Index >= NameIdx->getLocalTUCount())
670 return std::nullopt;
671 return NameIdx->getLocalTUOffset(*Index);
672}
673
674std::optional<uint64_t>
676 std::optional<uint64_t> Index = getLocalTUIndex();
677 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
678 if (!Index || *Index < NumLocalTUs)
679 return std::nullopt; // Invalid TU index or TU index is for a local TU
680 // The foreign TU index is the TU index minus the number of local TUs.
681 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
682 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
683 return std::nullopt; // Invalid foreign TU index.
684 return NameIdx->getForeignTUSignature(ForeignTUIndex);
685}
686
687std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
688 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
689 return Off->getAsUnsignedConstant();
690 return std::nullopt;
691}
692
695 // The offset of the accelerator table entry for the parent.
696 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
697 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
698
699 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
700 return std::nullopt;
701 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
702}
703
705 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
706 Expected<std::optional<Entry>> ParentEntry = getParentDIEEntry();
707 if (!ParentEntry) {
708 W.getOStream() << "<invalid offset data>";
709 consumeError(ParentEntry.takeError());
710 return;
711 }
712
713 if (!ParentEntry->has_value()) {
714 W.getOStream() << "<parent not indexed>";
715 return;
716 }
717
718 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
719 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
720}
721
723 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
724 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
725 assert(Abbr->Attributes.size() == Values.size());
726 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
727 auto Index = std::get<0>(Tuple).Index;
728 W.startLine() << formatv("{0}: ", Index);
729
730 auto FormValue = std::get<1>(Tuple);
731 if (Index == dwarf::Index::DW_IDX_parent)
732 dumpParentIdx(W, FormValue);
733 else
734 FormValue.dump(W.getOStream());
735 W.getOStream() << '\n';
736 }
737}
738
741 return inconvertibleErrorCode();
742}
743
745 assert(CU < Hdr.CompUnitCount);
746 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
747 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
748 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
749}
750
752 assert(TU < Hdr.LocalTypeUnitCount);
753 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
755 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
756 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
757}
758
760 assert(TU < Hdr.ForeignTypeUnitCount);
761 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
763 Offsets.CUsBase +
764 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
765 return Section.AccelSection.getU64(&Offset);
766}
767
770 const DWARFDataExtractor &AS = Section.AccelSection;
771 if (!AS.isValidOffset(*Offset))
773 "Incorrectly terminated entry list.");
774
775 uint32_t AbbrevCode = AS.getULEB128(Offset);
776 if (AbbrevCode == 0)
777 return make_error<SentinelError>();
778
779 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
780 if (AbbrevIt == Abbrevs.end())
781 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
782
783 Entry E(*this, *AbbrevIt);
784
785 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
786 for (auto &Value : E.Values) {
787 if (!Value.extractValue(AS, Offset, FormParams))
789 "Error extracting index attribute values.");
790 }
791 return std::move(E);
792}
793
796 assert(0 < Index && Index <= Hdr.NameCount);
797 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
798 uint64_t StringOffsetOffset =
799 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
800 uint64_t EntryOffsetOffset =
801 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
802 const DWARFDataExtractor &AS = Section.AccelSection;
803
804 uint64_t StringOffset =
805 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
806 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
807 EntryOffset += Offsets.EntriesBase;
808 return {Section.StringSection, Index, StringOffset, EntryOffset};
809}
810
813 assert(Bucket < Hdr.BucketCount);
814 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
815 return Section.AccelSection.getU32(&BucketOffset);
816}
817
819 assert(0 < Index && Index <= Hdr.NameCount);
820 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
821 return Section.AccelSection.getU32(&HashOffset);
822}
823
824// Returns true if we should continue scanning for entries, false if this is the
825// last (sentinel) entry). In case of a parsing error we also return false, as
826// it's not possible to recover this entry list (but the other lists may still
827// parse OK).
828bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
829 uint64_t *Offset) const {
830 uint64_t EntryId = *Offset;
831 auto EntryOr = getEntry(Offset);
832 if (!EntryOr) {
833 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
834 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
835 return false;
836 }
837
838 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
839 EntryOr->dump(W);
840 return true;
841}
842
843void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
844 const NameTableEntry &NTE,
845 std::optional<uint32_t> Hash) const {
846 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
847 if (Hash)
848 W.printHex("Hash", *Hash);
849
850 W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());
851 W.getOStream() << " \"" << NTE.getString() << "\"\n";
852
853 uint64_t EntryOffset = NTE.getEntryOffset();
854 while (dumpEntry(W, &EntryOffset))
855 /*empty*/;
856}
857
858void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
859 ListScope CUScope(W, "Compilation Unit offsets");
860 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
861 W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));
862}
863
864void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
865 if (Hdr.LocalTypeUnitCount == 0)
866 return;
867
868 ListScope TUScope(W, "Local Type Unit offsets");
869 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
870 W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,
871 getLocalTUOffset(TU));
872}
873
874void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
875 if (Hdr.ForeignTypeUnitCount == 0)
876 return;
877
878 ListScope TUScope(W, "Foreign Type Unit signatures");
879 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
880 W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
881 getForeignTUSignature(TU));
882 }
883}
884
885void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
886 ListScope AbbrevsScope(W, "Abbreviations");
887 std::vector<const Abbrev *> AbbrevsVect;
888 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
889 AbbrevsVect.push_back(&Abbr);
890 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
891 return LHS->AbbrevOffset < RHS->AbbrevOffset;
892 });
893 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
894 Abbr->dump(W);
895}
896
897void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
898 uint32_t Bucket) const {
899 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
900 uint32_t Index = getBucketArrayEntry(Bucket);
901 if (Index == 0) {
902 W.printString("EMPTY");
903 return;
904 }
905 if (Index > Hdr.NameCount) {
906 W.printString("Name index is invalid");
907 return;
908 }
909
910 for (; Index <= Hdr.NameCount; ++Index) {
911 uint32_t Hash = getHashArrayEntry(Index);
912 if (Hash % Hdr.BucketCount != Bucket)
913 break;
914
915 dumpName(W, getNameTableEntry(Index), Hash);
916 }
917}
918
920 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
921 Hdr.dump(W);
922 dumpCUs(W);
923 dumpLocalTUs(W);
924 dumpForeignTUs(W);
925 dumpAbbreviations(W);
926
927 if (Hdr.BucketCount > 0) {
928 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
929 dumpBucket(W, Bucket);
930 return;
931 }
932
933 W.startLine() << "Hash table not present\n";
934 for (const NameTableEntry &NTE : *this)
935 dumpName(W, NTE, std::nullopt);
936}
937
939 uint64_t Offset = 0;
941 NameIndex Next(*this, Offset);
942 if (Error E = Next.extract())
943 return E;
944 Offset = Next.getNextUnitOffset();
945 NameIndices.push_back(std::move(Next));
946 }
947 return Error::success();
948}
949
952 return make_range(ValueIterator(*this, Key), ValueIterator());
953}
954
956 ScopedPrinter W(OS);
957 for (const NameIndex &NI : NameIndices)
958 NI.dump(W);
959}
960
961std::optional<uint64_t>
962DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
963 const Header &Hdr = CurrentIndex->Hdr;
964 if (Hdr.BucketCount == 0) {
965 // No Hash Table, We need to search through all names in the Name Index.
966 for (const NameTableEntry &NTE : *CurrentIndex) {
967 if (NTE.sameNameAs(Key))
968 return NTE.getEntryOffset();
969 }
970 return std::nullopt;
971 }
972
973 // The Name Index has a Hash Table, so use that to speed up the search.
974 // Compute the Key Hash, if it has not been done already.
975 if (!Hash)
976 Hash = caseFoldingDjbHash(Key);
977 uint32_t Bucket = *Hash % Hdr.BucketCount;
978 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
979 if (Index == 0)
980 return std::nullopt; // Empty bucket
981
982 for (; Index <= Hdr.NameCount; ++Index) {
983 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
984 if (HashAtIndex % Hdr.BucketCount != Bucket)
985 return std::nullopt; // End of bucket
986 // Only compare names if the hashes match.
987 if (HashAtIndex != Hash)
988 continue;
989
990 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
991 if (NTE.sameNameAs(Key))
992 return NTE.getEntryOffset();
993 }
994 return std::nullopt;
995}
996
997bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
998 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
999 if (!EntryOr) {
1000 consumeError(EntryOr.takeError());
1001 return false;
1002 }
1003 CurrentEntry = std::move(*EntryOr);
1004 return true;
1005}
1006
1007bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1008 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1009 if (!Offset)
1010 return false;
1011 DataOffset = *Offset;
1012 return getEntryAtCurrentOffset();
1013}
1014
1015void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1016 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1017 CurrentIndex != End; ++CurrentIndex) {
1018 if (findInCurrentIndex())
1019 return;
1020 }
1021 setEnd();
1022}
1023
1024void DWARFDebugNames::ValueIterator::next() {
1025 assert(CurrentIndex && "Incrementing an end() iterator?");
1026
1027 // First try the next entry in the current Index.
1028 if (getEntryAtCurrentOffset())
1029 return;
1030
1031 // If we're a local iterator or we have reached the last Index, we're done.
1032 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1033 setEnd();
1034 return;
1035 }
1036
1037 // Otherwise, try the next index.
1038 ++CurrentIndex;
1039 searchFromStartOfCurrentIndex();
1040}
1041
1043 StringRef Key)
1044 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1045 Key(std::string(Key)) {
1046 searchFromStartOfCurrentIndex();
1047}
1048
1051 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1052 if (!findInCurrentIndex())
1053 setEnd();
1054}
1055
1058 if (NameIndices.empty())
1060 return make_range(ValueIterator(*this, Key), ValueIterator());
1061}
1062
1065 if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
1066 for (const auto &NI : *this) {
1067 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1068 CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1069 }
1070 }
1071 return CUToNameIndex.lookup(CUOffset);
1072}
1073
1075 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1076 (Name[1] == '[');
1077}
1078
1079std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1080 if (!isObjCSelector(Name))
1081 return std::nullopt;
1082 // "-[Atom setMass:]"
1083 StringRef ClassNameStart(Name.drop_front(2));
1084 size_t FirstSpace = ClassNameStart.find(' ');
1085 if (FirstSpace == StringRef::npos)
1086 return std::nullopt;
1087
1088 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1089 if (!SelectorStart.size())
1090 return std::nullopt;
1091
1093 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1094 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1095
1096 // "-[Class(Category) selector :withArg ...]"
1097 if (Ans.ClassName.back() == ')') {
1098 size_t OpenParens = Ans.ClassName.find('(');
1099 if (OpenParens != StringRef::npos) {
1100 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1101
1102 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1103 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1104 // does it this way.
1105 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1106 }
1107 }
1108 return Ans;
1109}
1110
1112 // We are looking for template parameters to strip from Name. e.g.
1113 //
1114 // operator<<B>
1115 //
1116 // We look for > at the end but if it does not contain any < then we
1117 // have something like operator>>. We check for the operator<=> case.
1118 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1119 return {};
1120
1121 // How many < until we have the start of the template parameters.
1122 size_t NumLeftAnglesToSkip = 1;
1123
1124 // If we have operator<=> then we need to skip its < as well.
1125 NumLeftAnglesToSkip += Name.count("<=>");
1126
1127 size_t RightAngleCount = Name.count('>');
1128 size_t LeftAngleCount = Name.count('<');
1129
1130 // If we have more < than > we have operator< or operator<<
1131 // we to account for their < as well.
1132 if (LeftAngleCount > RightAngleCount)
1133 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1134
1135 size_t StartOfTemplate = 0;
1136 while (NumLeftAnglesToSkip--)
1137 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1138
1139 return Name.substr(0, StartOfTemplate - 1);
1140}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
AMDGPU Kernel Attributes
#define offsetof(TYPE, MEMBER)
basic Basic Alias true
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:533
static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc()
static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE)
static DWARFDebugNames::Abbrev sentinelAbbrev()
static bool isObjCSelector(StringRef Name)
static Atom formatAtom(unsigned Atom)
This file contains constants used for implementing Dwarf debug support.
std::string Name
bool End
Definition: ELF_riscv.cpp:480
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
Definition: InlineInfo.cpp:109
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
Value * RHS
Value * LHS
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:202
std::optional< DWARFFormValue > lookup(HeaderData::AtomType Atom) const
Returns the value of the Atom in this Accelerator Entry, if the Entry contains such Atom.
std::optional< uint64_t > getDIESectionOffset() const
Returns the Section Offset of the Debug Info Entry associated with this Accelerator Entry or std::nul...
std::optional< dwarf::Tag > getTag() const override
Returns the Tag of the Debug Info Entry associated with this Accelerator Entry or std::nullopt if the...
std::optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...
Iterator(const AppleAcceleratorTable &Table, bool SetEnd=false)
An iterator for Entries all having the same string as key.
SameNameIterator(const AppleAcceleratorTable &AccelTable, uint64_t DataOffset)
Construct a new iterator for the entries at DataOffset.
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
iterator_range< SameNameIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
std::pair< uint64_t, dwarf::Tag > readAtoms(uint64_t *HashDataOffset)
Return information related to the DWARF DIE we're looking for when performing a lookup by name.
uint32_t getHashDataEntryLength() const
Returns the size of one HashData entry.
void dump(raw_ostream &OS) const override
ArrayRef< std::pair< HeaderData::AtomType, HeaderData::Form > > getAtomsDesc()
Return the Atom description, which can be used to interpret the raw values of the Accelerator Entries...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
SmallVector< DWARFFormValue, 3 > Values
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
std::pair< uint64_t, dwarf::DwarfFormat > getInitialLength(uint64_t *Off, Error *Err=nullptr) const
Extracts the DWARF "initial length" field, which can either be a 32-bit value smaller than 0xfffffff0...
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and applies a relocation to the result if one exists for the given offset.
DWARF v5-specific implementation of an Accelerator Entry.
std::optional< uint64_t > getLocalTUIndex() const
Returns the Index into the Local Type Unit list of the owning Name Index or std::nullopt if this Acce...
std::optional< uint64_t > getForeignTUTypeSignature() const override
Returns the type signature of the Type Unit associated with this Accelerator Entry or std::nullopt if...
std::optional< uint64_t > getRelatedCUIndex() const
Similar functionality to getCUIndex() but without the DW_IDX_type_unit restriction.
std::optional< uint64_t > getCUIndex() const
Returns the Index into the Compilation Unit list of the owning Name Index or std::nullopt if this Acc...
std::optional< uint64_t > getRelatedCUOffset() const
std::optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...
std::optional< uint64_t > getDIEUnitOffset() const
Returns the Offset of the DIE within the containing CU or TU.
Expected< std::optional< DWARFDebugNames::Entry > > getParentDIEEntry() const
Returns the Entry corresponding to the parent of the DIE represented by this Entry.
bool hasParentInformation() const
Returns true if this Entry has information about its parent DIE (i.e.
std::optional< DWARFFormValue > lookup(dwarf::Index Index) const
Returns the value of the Index Attribute in this Accelerator Entry, if the Entry contains such Attrib...
std::optional< uint64_t > getLocalTUOffset() const override
Returns the Offset of the Type Unit associated with this Accelerator Entry or std::nullopt if the Typ...
void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const
void dump(ScopedPrinter &W) const
Represents a single accelerator table within the DWARF v5 .debug_names section.
uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
uint64_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
void dump(ScopedPrinter &W) const
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
Expected< Entry > getEntry(uint64_t *Offset) const
NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
uint64_t getForeignTUSignature(uint32_t TU) const
Reads signature of foreign type unit TU. TU is 0-based.
Expected< Entry > getEntryAtRelativeOffset(uint64_t Offset) const
Returns the Entry at the relative Offset from the start of the Entry pool.
A single entry in the Name Table (DWARF v5 sect.
Error returned by NameIndex::getEntry to report it has reached the end of the entry list.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
ValueIterator()=default
End marker.
.debug_names section consists of one or more units.
const NameIndex * getCUNameIndex(uint64_t CUOffset)
Return the Name Index covering the compile unit at CUOffset, or nullptr if there is no Name Index cov...
const_iterator begin() const
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
void dump(raw_ostream &OS) const override
bool isFormClass(FormClass FC) const
bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)
Extracts a value in Data at offset *OffsetPtr.
std::optional< uint64_t > getAsUnsignedConstant() const
dwarf::Form getForm() const
uint64_t getRawUValue() const
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
size_t size() const
Return the number of bytes in the underlying buffer.
const char * getCStr(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
void skip(Cursor &C, uint64_t Length) const
Advance the Cursor position by the given number of bytes.
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
Base class for error info classes.
Definition: Error.h:45
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:594
char back() const
back - Get the last character in the string.
Definition: StringRef.h:146
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:565
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:282
static constexpr size_t npos
Definition: StringRef.h:52
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:601
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:416
LLVM Value Representation.
Definition: Value.h:74
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:105
StringRef AtomTypeString(unsigned Atom)
Definition: Dwarf.cpp:664
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:868
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Offsets
Offsets in bytes from the start of the input buffer.
Definition: SIInstrInfo.h:1589
StringRef AtomValueString(uint16_t Atom, unsigned Val)
Returns the symbolic string representing Val when used as a value for atom Atom.
Definition: Dwarf.cpp:749
DWARFDebugNames::DWARFDebugNamesOffsets findDebugNamesOffsets(uint64_t EndOfHeaderOffset, const DWARFDebugNames::Header &Hdr)
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ DWARF32
Definition: Dwarf.h:91
const uint32_t DW_INVALID_OFFSET
Identifier of an invalid DIE offset in the .debug_info section.
Definition: Dwarf.h:101
std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)
Get the fixed byte size for a given form.
Definition: Dwarf.cpp:771
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:1064
@ DW_ATOM_type_flags
Definition: Dwarf.h:916
@ DW_ATOM_die_tag
Definition: Dwarf.h:915
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition: Dwarf.h:912
@ DW_ATOM_cu_offset
Definition: Dwarf.h:913
NodeAddr< CodeNode * > Code
Definition: RDFGraph.h:388
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition: STLExtras.h:863
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:977
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2098
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1286
@ illegal_byte_sequence
detail::zippy< detail::zip_first, T, U, Args... > zip_first(T &&t, U &&u, Args &&...args)
zip iterator that, for the sake of efficiency, assumes the first iteratee to be the shortest.
Definition: STLExtras.h:876
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1647
std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H=5381)
Computes the Bernstein hash after folding the input according to the Dwarf 5 standard case folding ru...
Definition: DJB.cpp:72
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:292
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
Definition: DJB.h:21
std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)
If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1069
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
Abbreviation describing the encoding of Name Index entries.
void dump(ScopedPrinter &W) const
uint32_t Code
< Abbreviation offset in the .debug_names section
std::vector< AttributeEncoding > Attributes
List of index attributes.
dwarf::Tag Tag
Dwarf Tag of the described entity.
Index attribute and its encoding.
Offsets for the start of various important tables from the start of the section.
DWARF v5 Name Index header.
Error extract(const DWARFDataExtractor &AS, uint64_t *Offset)
void dump(ScopedPrinter &W) const
StringRef ClassName
For "-[A(Category) method:]", this would be "A(category)".
std::optional< std::string > MethodNameNoCategory
For "-[A(Category) method:]", this would be "A method:".
StringRef Selector
For "-[A(Category) method:]", this would be "method:".
std::optional< StringRef > ClassNameNoCategory
For "-[A(Category) method:]", this would be "A".
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition: Dwarf.h:1077