LLVM 22.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);
67 uint32_t NumAtoms = 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) {
77 uint16_t AtomType = AccelSection.getU16(&Offset);
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 =
82 dwarf::getFixedFormByteSize(AtomForm, FormParams);
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
101ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
102 AppleAcceleratorTable::HeaderData::Form>>
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,
176 SmallVectorImpl<DWARFFormValue> &AtomForms,
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>
283AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType AtomToFind) const {
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
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 const AppleAcceleratorTable &Table = getTable();
325 if (Offset == 0) {
326 // Always start looking for strings using a valid offset from the Offsets
327 // table. Entries are not always consecutive.
328 std::optional<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);
329 if (!OptOffset)
330 return setToEnd();
331 Offset = *OptOffset;
332 }
333 std::optional<uint32_t> StrOffset = Table.readStringOffsetAt(Offset);
334 if (!StrOffset)
335 return setToEnd();
336
337 // A zero denotes the end of the collision list. Skip to the next offset
338 // in the offsets table by setting the Offset to zero so we will grab the
339 // next offset from the offsets table.
340 if (*StrOffset == 0) {
341 Offset = 0;
342 return prepareNextStringOrEnd();
343 }
344 Current.StrOffset = *StrOffset;
345
346 std::optional<uint32_t> MaybeNumEntries = Table.readU32FromAccel(Offset);
347 if (!MaybeNumEntries || *MaybeNumEntries == 0)
348 return setToEnd();
349 NumEntriesToCome = *MaybeNumEntries;
350}
351
353 bool SetEnd)
354 : Current(Table), Offset(0), NumEntriesToCome(0) {
355 if (SetEnd)
356 setToEnd();
357 else
358 prepareNextEntryOrEnd();
359}
360
363 const auto EmptyRange =
364 make_range(SameNameIterator(*this, 0), SameNameIterator(*this, 0));
365 if (!IsValid)
366 return EmptyRange;
367
368 // Find the bucket.
369 uint32_t SearchHash = djbHash(Key);
370 uint32_t BucketIdx = hashToBucketIdx(SearchHash);
371 std::optional<uint32_t> HashIdx = idxOfHashInBucket(SearchHash, BucketIdx);
372 if (!HashIdx)
373 return EmptyRange;
374
375 std::optional<uint64_t> MaybeDataOffset = readIthOffset(*HashIdx);
376 if (!MaybeDataOffset)
377 return EmptyRange;
378
379 uint64_t DataOffset = *MaybeDataOffset;
380 if (DataOffset >= AccelSection.size())
381 return EmptyRange;
382
383 std::optional<uint32_t> StrOffset = readStringOffsetAt(DataOffset);
384 // Valid input and still have strings in this hash.
385 while (StrOffset && *StrOffset) {
386 std::optional<StringRef> MaybeStr = readStringFromStrSection(*StrOffset);
387 std::optional<uint32_t> NumEntries = this->readU32FromAccel(DataOffset);
388 if (!MaybeStr || !NumEntries)
389 return EmptyRange;
390 uint64_t EndOffset = DataOffset + *NumEntries * getHashDataEntryLength();
391 if (Key == *MaybeStr)
392 return make_range({*this, DataOffset},
393 SameNameIterator{*this, EndOffset});
394 DataOffset = EndOffset;
395 StrOffset = readStringOffsetAt(DataOffset);
396 }
397
398 return EmptyRange;
399}
400
401std::optional<uint32_t>
402AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,
403 uint32_t BucketIdx) const {
404 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);
405 if (!HashStartIdx)
406 return std::nullopt;
407
408 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {
409 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);
410 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))
411 break;
412 if (*MaybeHash == HashToFind)
413 return HashIdx;
414 }
415 return std::nullopt;
416}
417
418std::optional<StringRef> AppleAcceleratorTable::readStringFromStrSection(
419 uint64_t StringSectionOffset) const {
421 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);
422 if (E) {
423 consumeError(std::move(E));
424 return std::nullopt;
425 }
426 return Str;
427}
428
429std::optional<uint32_t>
430AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,
431 bool UseRelocation) const {
433 uint32_t Data = UseRelocation
434 ? AccelSection.getRelocatedValue(4, &Offset, nullptr, &E)
435 : AccelSection.getU32(&Offset, &E);
436 if (E) {
437 consumeError(std::move(E));
438 return std::nullopt;
439 }
440 return Data;
441}
442
444 DictScope HeaderScope(W, "Header");
445 W.printHex("Length", UnitLength);
446 W.printString("Format", dwarf::FormatString(Format));
447 W.printNumber("Version", Version);
448 W.printNumber("CU count", CompUnitCount);
449 W.printNumber("Local TU count", LocalTypeUnitCount);
450 W.printNumber("Foreign TU count", ForeignTypeUnitCount);
451 W.printNumber("Bucket count", BucketCount);
452 W.printNumber("Name count", NameCount);
453 W.printHex("Abbreviations table size", AbbrevTableSize);
454 W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
455}
456
458 uint64_t *Offset) {
459 auto HeaderError = [Offset = *Offset](Error E) {
461 "parsing .debug_names header at 0x%" PRIx64 ": %s",
462 Offset, toString(std::move(E)).c_str());
463 };
464
466 std::tie(UnitLength, Format) = AS.getInitialLength(C);
467
468 Version = AS.getU16(C);
469 AS.skip(C, 2); // padding
470 CompUnitCount = AS.getU32(C);
473 BucketCount = AS.getU32(C);
474 NameCount = AS.getU32(C);
477
478 if (!C)
479 return HeaderError(C.takeError());
480
483 "cannot read header augmentation"));
485 AS.getU8(C, reinterpret_cast<uint8_t *>(AugmentationString.data()),
487 *Offset = C.tell();
488 return C.takeError();
489}
490
492 DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
493 W.startLine() << formatv("Tag: {0}\n", Tag);
494
495 for (const auto &Attr : Attributes)
496 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
497}
498
500 return {dwarf::Index(0), dwarf::Form(0)};
501}
502
504 return AE == sentinelAttrEnc();
505}
506
510
511static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
512 return Abbr.Code == 0;
513}
514
515DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
516 return sentinelAbbrev();
517}
518
519DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
520 return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), 0, {});
521}
522
523Expected<DWARFDebugNames::AttributeEncoding>
524DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
525 if (*Offset >= Offsets.EntriesBase) {
527 "Incorrectly terminated abbreviation table.");
528 }
529
530 uint32_t Index = Section.AccelSection.getULEB128(Offset);
531 uint32_t Form = Section.AccelSection.getULEB128(Offset);
532 return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
533}
534
535Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
536DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
537 std::vector<AttributeEncoding> Result;
538 for (;;) {
539 auto AttrEncOr = extractAttributeEncoding(Offset);
540 if (!AttrEncOr)
541 return AttrEncOr.takeError();
542 if (isSentinel(*AttrEncOr))
543 return std::move(Result);
544
545 Result.emplace_back(*AttrEncOr);
546 }
547}
548
549Expected<DWARFDebugNames::Abbrev>
550DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
551 if (*Offset >= Offsets.EntriesBase) {
553 "Incorrectly terminated abbreviation table.");
554 }
555 const uint64_t AbbrevOffset = *Offset;
556 uint32_t Code = Section.AccelSection.getULEB128(Offset);
557 if (Code == 0)
558 return sentinelAbbrev();
559
560 uint32_t Tag = Section.AccelSection.getULEB128(Offset);
561 auto AttrEncOr = extractAttributeEncodings(Offset);
562 if (!AttrEncOr)
563 return AttrEncOr.takeError();
564 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
565}
566
567DWARFDebugNames::DWARFDebugNamesOffsets
569 const DWARFDebugNames::Header &Hdr) {
570 uint64_t DwarfSize = getDwarfOffsetByteSize(Hdr.Format);
572 Ret.CUsBase = EndOfHeaderOffset;
573 Ret.BucketsBase = Ret.CUsBase + Hdr.CompUnitCount * DwarfSize +
574 Hdr.LocalTypeUnitCount * DwarfSize +
575 Hdr.ForeignTypeUnitCount * 8;
576 Ret.HashesBase = Ret.BucketsBase + Hdr.BucketCount * 4;
578 Ret.HashesBase + (Hdr.BucketCount > 0 ? Hdr.NameCount * 4 : 0);
579 Ret.EntryOffsetsBase = Ret.StringOffsetsBase + Hdr.NameCount * DwarfSize;
580 Ret.EntriesBase =
581 Ret.EntryOffsetsBase + Hdr.NameCount * DwarfSize + Hdr.AbbrevTableSize;
582 return Ret;
583}
584
586 const DWARFDataExtractor &AS = Section.AccelSection;
587 uint64_t EndOfHeaderOffset = Base;
588 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
589 return E;
590
591 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
592 Offsets = dwarf::findDebugNamesOffsets(EndOfHeaderOffset, Hdr);
593
595 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
596
597 if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
599 "Section too small: cannot read abbreviations.");
600
601 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
602
603 for (;;) {
604 auto AbbrevOr = extractAbbrev(&Offset);
605 if (!AbbrevOr)
606 return AbbrevOr.takeError();
607 if (isSentinel(*AbbrevOr))
608 return Error::success();
609
610 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
612 "Duplicate abbreviation code.");
613 }
614}
615
616DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
617 : NameIdx(&NameIdx), Abbr(&Abbr) {
618 // This merely creates form values. It is up to the caller
619 // (NameIndex::getEntry) to populate them.
620 Values.reserve(Abbr.Attributes.size());
621 for (const auto &Attr : Abbr.Attributes)
622 Values.emplace_back(Attr.Form);
623}
624
625std::optional<DWARFFormValue>
627 assert(Abbr->Attributes.size() == Values.size());
628 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
629 if (std::get<0>(Tuple).Index == Index)
630 return std::get<1>(Tuple);
631 }
632 return std::nullopt;
633}
634
636 return lookup(dwarf::DW_IDX_parent).has_value();
637}
638
639std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
640 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
641 return Off->getAsReferenceUVal();
642 return std::nullopt;
643}
644
645std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
646 // Return the DW_IDX_compile_unit attribute value if it is specified.
647 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
648 return Off->getAsUnsignedConstant();
649 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
650 // implicitly refer to the single CU.
651 if (NameIdx->getCUCount() == 1)
652 return 0;
653 return std::nullopt;
654}
655
656std::optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
657 // Return the DW_IDX_compile_unit attribute value but only if we don't have a
658 // DW_IDX_type_unit attribute. Use Entry::getRelatedCUIndex() to get the
659 // associated CU index if this behaviour is not desired.
660 if (lookup(dwarf::DW_IDX_type_unit).has_value())
661 return std::nullopt;
662 return getRelatedCUIndex();
663}
664
665std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
666 std::optional<uint64_t> Index = getCUIndex();
667 if (!Index || *Index >= NameIdx->getCUCount())
668 return std::nullopt;
669 return NameIdx->getCUOffset(*Index);
670}
671
672std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
673 std::optional<uint64_t> Index = getRelatedCUIndex();
674 if (!Index || *Index >= NameIdx->getCUCount())
675 return std::nullopt;
676 return NameIdx->getCUOffset(*Index);
677}
678
679std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
680 std::optional<uint64_t> Index = getTUIndex();
681 if (!Index || *Index >= NameIdx->getLocalTUCount())
682 return std::nullopt;
683 return NameIdx->getLocalTUOffset(*Index);
684}
685
686std::optional<uint64_t>
688 std::optional<uint64_t> Index = getTUIndex();
689 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
690 if (!Index || *Index < NumLocalTUs)
691 return std::nullopt; // Invalid TU index or TU index is for a local TU
692 // The foreign TU index is the TU index minus the number of local TUs.
693 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
694 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
695 return std::nullopt; // Invalid foreign TU index.
696 return NameIdx->getForeignTUSignature(ForeignTUIndex);
697}
698
699std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
700 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
701 return Off->getAsUnsignedConstant();
702 return std::nullopt;
703}
704
707 // The offset of the accelerator table entry for the parent.
708 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
709 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
710
711 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
712 return std::nullopt;
713 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
714}
715
717 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
719 if (!ParentEntry) {
720 W.getOStream() << "<invalid offset data>";
721 consumeError(ParentEntry.takeError());
722 return;
723 }
724
725 if (!ParentEntry->has_value()) {
726 W.getOStream() << "<parent not indexed>";
727 return;
728 }
729
730 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
731 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
732}
733
735 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
736 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
737 assert(Abbr->Attributes.size() == Values.size());
738 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
739 auto Index = std::get<0>(Tuple).Index;
740 W.startLine() << formatv("{0}: ", Index);
741
742 auto FormValue = std::get<1>(Tuple);
743 if (Index == dwarf::Index::DW_IDX_parent)
744 dumpParentIdx(W, FormValue);
745 else
746 FormValue.dump(W.getOStream());
747 W.getOStream() << '\n';
748 }
749}
750
755
757 assert(CU < Hdr.CompUnitCount);
758 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
759 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
760 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
761}
762
764 assert(TU < Hdr.LocalTypeUnitCount);
765 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
767 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
768 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
769}
770
772 assert(TU < Hdr.ForeignTypeUnitCount);
773 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
775 Offsets.CUsBase +
776 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
777 return Section.AccelSection.getU64(&Offset);
778}
779
782 const DWARFDataExtractor &AS = Section.AccelSection;
783 if (!AS.isValidOffset(*Offset))
785 "Incorrectly terminated entry list.");
786
787 uint32_t AbbrevCode = AS.getULEB128(Offset);
788 if (AbbrevCode == 0)
790
791 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
792 if (AbbrevIt == Abbrevs.end())
793 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
794
795 Entry E(*this, *AbbrevIt);
796
797 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
798 for (auto &Value : E.Values) {
799 if (!Value.extractValue(AS, Offset, FormParams))
801 "Error extracting index attribute values.");
802 }
803 return std::move(E);
804}
805
808 assert(0 < Index && Index <= Hdr.NameCount);
809 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
810 uint64_t StringOffsetOffset =
811 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
812 uint64_t EntryOffsetOffset =
813 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
814 const DWARFDataExtractor &AS = Section.AccelSection;
815
816 uint64_t StringOffset =
817 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
818 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
819 EntryOffset += Offsets.EntriesBase;
820 return {Section.StringSection, Index, StringOffset, EntryOffset};
821}
822
825 assert(Bucket < Hdr.BucketCount);
826 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
827 return Section.AccelSection.getU32(&BucketOffset);
828}
829
831 assert(0 < Index && Index <= Hdr.NameCount);
832 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
833 return Section.AccelSection.getU32(&HashOffset);
834}
835
836// Returns true if we should continue scanning for entries, false if this is the
837// last (sentinel) entry). In case of a parsing error we also return false, as
838// it's not possible to recover this entry list (but the other lists may still
839// parse OK).
840bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
841 uint64_t *Offset) const {
842 uint64_t EntryId = *Offset;
843 auto EntryOr = getEntry(Offset);
844 if (!EntryOr) {
845 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
846 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
847 return false;
848 }
849
850 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
851 EntryOr->dump(W);
852 return true;
853}
854
855void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
856 const NameTableEntry &NTE,
857 std::optional<uint32_t> Hash) const {
858 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
859 if (Hash)
860 W.printHex("Hash", *Hash);
861
862 W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());
863 W.getOStream() << " \"" << NTE.getString() << "\"\n";
864
865 uint64_t EntryOffset = NTE.getEntryOffset();
866 while (dumpEntry(W, &EntryOffset))
867 /*empty*/;
868}
869
870void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
871 ListScope CUScope(W, "Compilation Unit offsets");
872 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
873 W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));
874}
875
876void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
877 if (Hdr.LocalTypeUnitCount == 0)
878 return;
879
880 ListScope TUScope(W, "Local Type Unit offsets");
881 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
882 W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,
883 getLocalTUOffset(TU));
884}
885
886void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
887 if (Hdr.ForeignTypeUnitCount == 0)
888 return;
889
890 ListScope TUScope(W, "Foreign Type Unit signatures");
891 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
892 W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
893 getForeignTUSignature(TU));
894 }
895}
896
897void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
898 ListScope AbbrevsScope(W, "Abbreviations");
899 std::vector<const Abbrev *> AbbrevsVect;
900 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
901 AbbrevsVect.push_back(&Abbr);
902 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
903 return LHS->AbbrevOffset < RHS->AbbrevOffset;
904 });
905 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
906 Abbr->dump(W);
907}
908
909void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
910 uint32_t Bucket) const {
911 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
912 uint32_t Index = getBucketArrayEntry(Bucket);
913 if (Index == 0) {
914 W.printString("EMPTY");
915 return;
916 }
917 if (Index > Hdr.NameCount) {
918 W.printString("Name index is invalid");
919 return;
920 }
921
922 for (; Index <= Hdr.NameCount; ++Index) {
923 uint32_t Hash = getHashArrayEntry(Index);
924 if (Hash % Hdr.BucketCount != Bucket)
925 break;
926
927 dumpName(W, getNameTableEntry(Index), Hash);
928 }
929}
930
932 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
933 Hdr.dump(W);
934 dumpCUs(W);
935 dumpLocalTUs(W);
936 dumpForeignTUs(W);
937 dumpAbbreviations(W);
938
939 if (Hdr.BucketCount > 0) {
940 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
941 dumpBucket(W, Bucket);
942 return;
943 }
944
945 W.startLine() << "Hash table not present\n";
946 for (const NameTableEntry &NTE : *this)
947 dumpName(W, NTE, std::nullopt);
948}
949
951 uint64_t Offset = 0;
952 while (AccelSection.isValidOffset(Offset)) {
953 NameIndex Next(*this, Offset);
954 if (Error E = Next.extract())
955 return E;
956 Offset = Next.getNextUnitOffset();
957 NameIndices.push_back(std::move(Next));
958 }
959 return Error::success();
960}
961
966
968 ScopedPrinter W(OS);
969 for (const NameIndex &NI : NameIndices)
970 NI.dump(W);
971}
972
973std::optional<uint64_t>
974DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
975 const Header &Hdr = CurrentIndex->Hdr;
976 if (Hdr.BucketCount == 0) {
977 // No Hash Table, We need to search through all names in the Name Index.
978 for (const NameTableEntry &NTE : *CurrentIndex) {
979 if (NTE.sameNameAs(Key))
980 return NTE.getEntryOffset();
981 }
982 return std::nullopt;
983 }
984
985 // The Name Index has a Hash Table, so use that to speed up the search.
986 // Compute the Key Hash, if it has not been done already.
987 if (!Hash)
988 Hash = caseFoldingDjbHash(Key);
989 uint32_t Bucket = *Hash % Hdr.BucketCount;
990 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
991 if (Index == 0)
992 return std::nullopt; // Empty bucket
993
994 for (; Index <= Hdr.NameCount; ++Index) {
995 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
996 if (HashAtIndex % Hdr.BucketCount != Bucket)
997 return std::nullopt; // End of bucket
998 // Only compare names if the hashes match.
999 if (HashAtIndex != Hash)
1000 continue;
1001
1002 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
1003 if (NTE.sameNameAs(Key))
1004 return NTE.getEntryOffset();
1005 }
1006 return std::nullopt;
1007}
1008
1009bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
1010 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
1011 if (!EntryOr) {
1012 consumeError(EntryOr.takeError());
1013 return false;
1014 }
1015 CurrentEntry = std::move(*EntryOr);
1016 return true;
1017}
1018
1019bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1020 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1021 if (!Offset)
1022 return false;
1023 DataOffset = *Offset;
1024 return getEntryAtCurrentOffset();
1025}
1026
1027void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1028 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1029 CurrentIndex != End; ++CurrentIndex) {
1030 if (findInCurrentIndex())
1031 return;
1032 }
1033 setEnd();
1034}
1035
1036void DWARFDebugNames::ValueIterator::next() {
1037 assert(CurrentIndex && "Incrementing an end() iterator?");
1038
1039 // First try the next entry in the current Index.
1040 if (getEntryAtCurrentOffset())
1041 return;
1042
1043 // If we're a local iterator or we have reached the last Index, we're done.
1044 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1045 setEnd();
1046 return;
1047 }
1048
1049 // Otherwise, try the next index.
1050 ++CurrentIndex;
1051 searchFromStartOfCurrentIndex();
1052}
1053
1055 StringRef Key)
1056 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1057 Key(std::string(Key)) {
1058 searchFromStartOfCurrentIndex();
1059}
1060
1063 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1064 if (!findInCurrentIndex())
1065 setEnd();
1066}
1067
1070 if (NameIndices.empty())
1072 return make_range(ValueIterator(*this, Key), ValueIterator());
1073}
1074
1077 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
1078 for (const auto &NI : *this) {
1079 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1080 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1081 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
1082 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
1083 }
1084 }
1085 return UnitOffsetToNameIndex.lookup(UnitOffset);
1086}
1087
1088static bool isObjCSelector(StringRef Name) {
1089 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1090 (Name[1] == '[');
1091}
1092
1093std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1094 if (!isObjCSelector(Name))
1095 return std::nullopt;
1096 // "-[Atom setMass:]"
1097 StringRef ClassNameStart(Name.drop_front(2));
1098 size_t FirstSpace = ClassNameStart.find(' ');
1099 if (FirstSpace == StringRef::npos)
1100 return std::nullopt;
1101
1102 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1103 if (!SelectorStart.size())
1104 return std::nullopt;
1105
1107 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1108 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1109
1110 // "-[Class(Category) selector :withArg ...]"
1111 if (Ans.ClassName.back() == ')') {
1112 size_t OpenParens = Ans.ClassName.find('(');
1113 if (OpenParens != StringRef::npos) {
1114 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1115
1116 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1117 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1118 // does it this way.
1119 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1120 }
1121 }
1122 return Ans;
1123}
1124
1125std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
1126 // We are looking for template parameters to strip from Name. e.g.
1127 //
1128 // operator<<B>
1129 //
1130 // We look for > at the end but if it does not contain any < then we
1131 // have something like operator>>. We check for the operator<=> case.
1132 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1133 return {};
1134
1135 // How many < until we have the start of the template parameters.
1136 size_t NumLeftAnglesToSkip = 1;
1137
1138 // If we have operator<=> then we need to skip its < as well.
1139 NumLeftAnglesToSkip += Name.count("<=>");
1140
1141 size_t RightAngleCount = Name.count('>');
1142 size_t LeftAngleCount = Name.count('<');
1143
1144 // If we have more < than > we have operator< or operator<<
1145 // we to account for their < as well.
1146 if (LeftAngleCount > RightAngleCount)
1147 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1148
1149 size_t StartOfTemplate = 0;
1150 while (NumLeftAnglesToSkip--)
1151 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1152
1153 return Name.substr(0, StartOfTemplate - 1);
1154}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
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.
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.
#define offsetof(TYPE, MEMBER)
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:203
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 ...
LLVM_ABI Iterator(const AppleAcceleratorTable &Table, bool SetEnd=false)
An iterator for Entries all having the same string as key.
LLVM_ABI 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.
AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)
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:40
SmallVector< DWARFFormValue, 3 > Values
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...
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
DWARF v5-specific implementation of an Accelerator Entry.
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< uint64_t > getTUIndex() const
Returns the index of the Type Unit of the owning Name Index or std::nullopt if this Accelerator Entry...
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.
LLVM_ABI uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
LLVM_ABI uint64_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
LLVM_ABI uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
LLVM_ABI void dump(ScopedPrinter &W) const
LLVM_ABI iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
LLVM_ABI uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
LLVM_ABI Expected< Entry > getEntry(uint64_t *Offset) const
LLVM_ABI NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
LLVM_ABI uint64_t getForeignTUSignature(uint32_t TU) const
Reads signature of foreign type unit TU. TU is 0-based.
A single entry in the Name Table (DWARF v5 sect.
uint64_t getEntryOffset() const
Returns the offset of the first Entry in the list.
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.
const_iterator begin() const
DWARFDebugNames(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
const NameIndex * getCUOrTUNameIndex(uint64_t UnitOffset)
Return the Name Index covering the compile unit or local type unit at UnitOffset, or nullptr if there...
void dump(raw_ostream &OS) const override
LLVM_ABI bool isFormClass(FormClass FC) const
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
LLVM_ABI uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
LLVM_ABI uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
LLVM_ABI uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
LLVM_ABI 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:44
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static constexpr size_t npos
Definition StringRef.h:57
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:611
char back() const
back - Get the last character in the string.
Definition StringRef.h:155
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
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:582
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:293
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:618
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
LLVM Value Representation.
Definition Value.h:75
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:53
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
Definition Dwarf.cpp:105
LLVM_ABI StringRef AtomTypeString(unsigned Atom)
Definition Dwarf.cpp:814
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1022
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
Offsets
Offsets in bytes from the start of the input buffer.
LLVM_ABI StringRef AtomValueString(uint16_t Atom, unsigned Val)
Returns the symbolic string representing Val when used as a value for atom Atom.
Definition Dwarf.cpp:903
LLVM_ABI DWARFDebugNames::DWARFDebugNamesOffsets findDebugNamesOffsets(uint64_t EndOfHeaderOffset, const DWARFDebugNames::Header &Hdr)
@ DWARF32
Definition Dwarf.h:93
const uint32_t DW_INVALID_OFFSET
Identifier of an invalid DIE offset in the .debug_info section.
Definition Dwarf.h:103
LLVM_ABI std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)
Get the fixed byte size for a given form.
Definition Dwarf.cpp:925
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1097
@ DW_ATOM_type_flags
Definition Dwarf.h:944
@ DW_ATOM_die_tag
Definition Dwarf.h:943
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition Dwarf.h:940
@ DW_ATOM_cu_offset
Definition Dwarf.h:941
NodeAddr< CodeNode * > Code
Definition RDFGraph.h:388
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
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:839
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:990
LLVM_ABI 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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2136
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ illegal_byte_sequence
Definition Errc.h:52
@ not_supported
Definition Errc.h:69
@ io_error
Definition Errc.h:58
@ invalid_argument
Definition Errc.h:56
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:302
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:852
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1622
LLVM_ABI 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:129
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
LLVM_ABI 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:144
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
Definition DJB.h:22
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LLVM_ABI 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:1083
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
Abbreviation describing the encoding of Name Index entries.
LLVM_ABI 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.
Offsets for the start of various important tables from the start of the section.
DWARF v5 Name Index header.
LLVM_ABI Error extract(const DWARFDataExtractor &AS, uint64_t *Offset)
LLVM_ABI 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:1110