LLVM 19.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 hdrSize = Base;
576 if (Error E = Hdr.extract(AS, &hdrSize))
577 return E;
578
579 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
580 Offsets = dwarf::findDebugNamesOffsets(hdrSize, 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::getCUIndex() const {
634 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
635 return Off->getAsUnsignedConstant();
636 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
637 // implicitly refer to the single CU, but only if we don't have a
638 // DW_IDX_type_unit.
639 if (lookup(dwarf::DW_IDX_type_unit).has_value())
640 return std::nullopt;
641 if (NameIdx->getCUCount() == 1)
642 return 0;
643 return std::nullopt;
644}
645
646std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
647 std::optional<uint64_t> Index = getCUIndex();
648 if (!Index || *Index >= NameIdx->getCUCount())
649 return std::nullopt;
650 return NameIdx->getCUOffset(*Index);
651}
652
653std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
654 std::optional<uint64_t> Index = getLocalTUIndex();
655 if (!Index || *Index >= NameIdx->getLocalTUCount())
656 return std::nullopt;
657 return NameIdx->getLocalTUOffset(*Index);
658}
659
660std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
661 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
662 return Off->getAsUnsignedConstant();
663 return std::nullopt;
664}
665
668 // The offset of the accelerator table entry for the parent.
669 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
670 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
671
672 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
673 return std::nullopt;
674 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
675}
676
678 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
679 Expected<std::optional<Entry>> ParentEntry = getParentDIEEntry();
680 if (!ParentEntry) {
681 W.getOStream() << "<invalid offset data>";
682 consumeError(ParentEntry.takeError());
683 return;
684 }
685
686 if (!ParentEntry->has_value()) {
687 W.getOStream() << "<parent not indexed>";
688 return;
689 }
690
691 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
692 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
693}
694
696 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
697 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
698 assert(Abbr->Attributes.size() == Values.size());
699 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
700 auto Index = std::get<0>(Tuple).Index;
701 W.startLine() << formatv("{0}: ", Index);
702
703 auto FormValue = std::get<1>(Tuple);
704 if (Index == dwarf::Index::DW_IDX_parent)
705 dumpParentIdx(W, FormValue);
706 else
707 FormValue.dump(W.getOStream());
708 W.getOStream() << '\n';
709 }
710}
711
714 return inconvertibleErrorCode();
715}
716
718 assert(CU < Hdr.CompUnitCount);
719 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
720 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
721 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
722}
723
725 assert(TU < Hdr.LocalTypeUnitCount);
726 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
728 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
729 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
730}
731
733 assert(TU < Hdr.ForeignTypeUnitCount);
734 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
736 Offsets.CUsBase +
737 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
738 return Section.AccelSection.getU64(&Offset);
739}
740
743 const DWARFDataExtractor &AS = Section.AccelSection;
744 if (!AS.isValidOffset(*Offset))
746 "Incorrectly terminated entry list.");
747
748 uint32_t AbbrevCode = AS.getULEB128(Offset);
749 if (AbbrevCode == 0)
750 return make_error<SentinelError>();
751
752 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
753 if (AbbrevIt == Abbrevs.end())
754 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
755
756 Entry E(*this, *AbbrevIt);
757
758 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
759 for (auto &Value : E.Values) {
760 if (!Value.extractValue(AS, Offset, FormParams))
762 "Error extracting index attribute values.");
763 }
764 return std::move(E);
765}
766
769 assert(0 < Index && Index <= Hdr.NameCount);
770 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
771 uint64_t StringOffsetOffset =
772 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
773 uint64_t EntryOffsetOffset =
774 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
775 const DWARFDataExtractor &AS = Section.AccelSection;
776
777 uint64_t StringOffset =
778 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
779 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
780 EntryOffset += Offsets.EntriesBase;
781 return {Section.StringSection, Index, StringOffset, EntryOffset};
782}
783
786 assert(Bucket < Hdr.BucketCount);
787 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
788 return Section.AccelSection.getU32(&BucketOffset);
789}
790
792 assert(0 < Index && Index <= Hdr.NameCount);
793 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
794 return Section.AccelSection.getU32(&HashOffset);
795}
796
797// Returns true if we should continue scanning for entries, false if this is the
798// last (sentinel) entry). In case of a parsing error we also return false, as
799// it's not possible to recover this entry list (but the other lists may still
800// parse OK).
801bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
802 uint64_t *Offset) const {
803 uint64_t EntryId = *Offset;
804 auto EntryOr = getEntry(Offset);
805 if (!EntryOr) {
806 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
807 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
808 return false;
809 }
810
811 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
812 EntryOr->dump(W);
813 return true;
814}
815
816void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
817 const NameTableEntry &NTE,
818 std::optional<uint32_t> Hash) const {
819 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
820 if (Hash)
821 W.printHex("Hash", *Hash);
822
823 W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());
824 W.getOStream() << " \"" << NTE.getString() << "\"\n";
825
826 uint64_t EntryOffset = NTE.getEntryOffset();
827 while (dumpEntry(W, &EntryOffset))
828 /*empty*/;
829}
830
831void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
832 ListScope CUScope(W, "Compilation Unit offsets");
833 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
834 W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));
835}
836
837void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
838 if (Hdr.LocalTypeUnitCount == 0)
839 return;
840
841 ListScope TUScope(W, "Local Type Unit offsets");
842 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
843 W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,
844 getLocalTUOffset(TU));
845}
846
847void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
848 if (Hdr.ForeignTypeUnitCount == 0)
849 return;
850
851 ListScope TUScope(W, "Foreign Type Unit signatures");
852 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
853 W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
854 getForeignTUSignature(TU));
855 }
856}
857
858void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
859 ListScope AbbrevsScope(W, "Abbreviations");
860 std::vector<const Abbrev *> AbbrevsVect;
861 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
862 AbbrevsVect.push_back(&Abbr);
863 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
864 return LHS->AbbrevOffset < RHS->AbbrevOffset;
865 });
866 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
867 Abbr->dump(W);
868}
869
870void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
871 uint32_t Bucket) const {
872 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
873 uint32_t Index = getBucketArrayEntry(Bucket);
874 if (Index == 0) {
875 W.printString("EMPTY");
876 return;
877 }
878 if (Index > Hdr.NameCount) {
879 W.printString("Name index is invalid");
880 return;
881 }
882
883 for (; Index <= Hdr.NameCount; ++Index) {
884 uint32_t Hash = getHashArrayEntry(Index);
885 if (Hash % Hdr.BucketCount != Bucket)
886 break;
887
888 dumpName(W, getNameTableEntry(Index), Hash);
889 }
890}
891
893 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
894 Hdr.dump(W);
895 dumpCUs(W);
896 dumpLocalTUs(W);
897 dumpForeignTUs(W);
898 dumpAbbreviations(W);
899
900 if (Hdr.BucketCount > 0) {
901 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
902 dumpBucket(W, Bucket);
903 return;
904 }
905
906 W.startLine() << "Hash table not present\n";
907 for (const NameTableEntry &NTE : *this)
908 dumpName(W, NTE, std::nullopt);
909}
910
912 uint64_t Offset = 0;
914 NameIndex Next(*this, Offset);
915 if (Error E = Next.extract())
916 return E;
917 Offset = Next.getNextUnitOffset();
918 NameIndices.push_back(std::move(Next));
919 }
920 return Error::success();
921}
922
925 return make_range(ValueIterator(*this, Key), ValueIterator());
926}
927
929 ScopedPrinter W(OS);
930 for (const NameIndex &NI : NameIndices)
931 NI.dump(W);
932}
933
934std::optional<uint64_t>
935DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
936 const Header &Hdr = CurrentIndex->Hdr;
937 if (Hdr.BucketCount == 0) {
938 // No Hash Table, We need to search through all names in the Name Index.
939 for (const NameTableEntry &NTE : *CurrentIndex) {
940 if (NTE.sameNameAs(Key))
941 return NTE.getEntryOffset();
942 }
943 return std::nullopt;
944 }
945
946 // The Name Index has a Hash Table, so use that to speed up the search.
947 // Compute the Key Hash, if it has not been done already.
948 if (!Hash)
949 Hash = caseFoldingDjbHash(Key);
950 uint32_t Bucket = *Hash % Hdr.BucketCount;
951 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
952 if (Index == 0)
953 return std::nullopt; // Empty bucket
954
955 for (; Index <= Hdr.NameCount; ++Index) {
956 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
957 if (HashAtIndex % Hdr.BucketCount != Bucket)
958 return std::nullopt; // End of bucket
959 // Only compare names if the hashes match.
960 if (HashAtIndex != Hash)
961 continue;
962
963 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
964 if (NTE.sameNameAs(Key))
965 return NTE.getEntryOffset();
966 }
967 return std::nullopt;
968}
969
970bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
971 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
972 if (!EntryOr) {
973 consumeError(EntryOr.takeError());
974 return false;
975 }
976 CurrentEntry = std::move(*EntryOr);
977 return true;
978}
979
980bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
981 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
982 if (!Offset)
983 return false;
984 DataOffset = *Offset;
985 return getEntryAtCurrentOffset();
986}
987
988void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
989 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
990 CurrentIndex != End; ++CurrentIndex) {
991 if (findInCurrentIndex())
992 return;
993 }
994 setEnd();
995}
996
997void DWARFDebugNames::ValueIterator::next() {
998 assert(CurrentIndex && "Incrementing an end() iterator?");
999
1000 // First try the next entry in the current Index.
1001 if (getEntryAtCurrentOffset())
1002 return;
1003
1004 // If we're a local iterator or we have reached the last Index, we're done.
1005 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1006 setEnd();
1007 return;
1008 }
1009
1010 // Otherwise, try the next index.
1011 ++CurrentIndex;
1012 searchFromStartOfCurrentIndex();
1013}
1014
1016 StringRef Key)
1017 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1018 Key(std::string(Key)) {
1019 searchFromStartOfCurrentIndex();
1020}
1021
1024 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1025 if (!findInCurrentIndex())
1026 setEnd();
1027}
1028
1031 if (NameIndices.empty())
1033 return make_range(ValueIterator(*this, Key), ValueIterator());
1034}
1035
1038 if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
1039 for (const auto &NI : *this) {
1040 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1041 CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1042 }
1043 }
1044 return CUToNameIndex.lookup(CUOffset);
1045}
1046
1048 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1049 (Name[1] == '[');
1050}
1051
1052std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1053 if (!isObjCSelector(Name))
1054 return std::nullopt;
1055 // "-[Atom setMass:]"
1056 StringRef ClassNameStart(Name.drop_front(2));
1057 size_t FirstSpace = ClassNameStart.find(' ');
1058 if (FirstSpace == StringRef::npos)
1059 return std::nullopt;
1060
1061 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1062 if (!SelectorStart.size())
1063 return std::nullopt;
1064
1066 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1067 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1068
1069 // "-[Class(Category) selector :withArg ...]"
1070 if (Ans.ClassName.back() == ')') {
1071 size_t OpenParens = Ans.ClassName.find('(');
1072 if (OpenParens != StringRef::npos) {
1073 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1074
1075 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1076 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1077 // does it this way.
1078 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1079 }
1080 }
1081 return Ans;
1082}
1083
1085 // We are looking for template parameters to strip from Name. e.g.
1086 //
1087 // operator<<B>
1088 //
1089 // We look for > at the end but if it does not contain any < then we
1090 // have something like operator>>. We check for the operator<=> case.
1091 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1092 return {};
1093
1094 // How many < until we have the start of the template parameters.
1095 size_t NumLeftAnglesToSkip = 1;
1096
1097 // If we have operator<=> then we need to skip its < as well.
1098 NumLeftAnglesToSkip += Name.count("<=>");
1099
1100 size_t RightAngleCount = Name.count('>');
1101 size_t LeftAngleCount = Name.count('<');
1102
1103 // If we have more < than > we have operator< or operator<<
1104 // we to account for their < as well.
1105 if (LeftAngleCount > RightAngleCount)
1106 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1107
1108 size_t StartOfTemplate = 0;
1109 while (NumLeftAnglesToSkip--)
1110 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1111
1112 return Name.substr(0, StartOfTemplate - 1);
1113}
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:529
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 > 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 > 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:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
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:605
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:576
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:293
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:612
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:622
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:826
@ 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:1522
StringRef AtomValueString(uint16_t Atom, unsigned Val)
Returns the symbolic string representing Val when used as a value for atom Atom.
Definition: Dwarf.cpp:707
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:729
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:739
@ DW_ATOM_type_flags
Definition: Dwarf.h:599
@ DW_ATOM_die_tag
Definition: Dwarf.h:598
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition: Dwarf.h:595
@ DW_ATOM_cu_offset
Definition: Dwarf.h:596
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:456
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:970
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:90
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:2073
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1258
@ 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:293
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:1041
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:752