LLVM 23.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_" << formatv("{0: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() << formatv("String: {0:x8}", 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() << formatv("Atom[{0}]: ", 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
515Expected<DWARFDebugNames::AttributeEncoding>
516DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
517 if (*Offset >= Offsets.EntriesBase) {
519 "Incorrectly terminated abbreviation table.");
520 }
521
522 uint32_t Index = Section.AccelSection.getULEB128(Offset);
523 uint32_t Form = Section.AccelSection.getULEB128(Offset);
524 return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
525}
526
527Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
528DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
529 std::vector<AttributeEncoding> Result;
530 for (;;) {
531 auto AttrEncOr = extractAttributeEncoding(Offset);
532 if (!AttrEncOr)
533 return AttrEncOr.takeError();
534 if (isSentinel(*AttrEncOr))
535 return std::move(Result);
536
537 Result.emplace_back(*AttrEncOr);
538 }
539}
540
541Expected<DWARFDebugNames::Abbrev>
542DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
543 if (*Offset >= Offsets.EntriesBase) {
545 "Incorrectly terminated abbreviation table.");
546 }
547 const uint64_t AbbrevOffset = *Offset;
548 uint32_t Code = Section.AccelSection.getULEB128(Offset);
549 if (Code == 0)
550 return sentinelAbbrev();
551
552 uint32_t Tag = Section.AccelSection.getULEB128(Offset);
553 auto AttrEncOr = extractAttributeEncodings(Offset);
554 if (!AttrEncOr)
555 return AttrEncOr.takeError();
556 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
557}
558
559DWARFDebugNames::DWARFDebugNamesOffsets
561 const DWARFDebugNames::Header &Hdr) {
562 uint64_t DwarfSize = getDwarfOffsetByteSize(Hdr.Format);
564 Ret.CUsBase = EndOfHeaderOffset;
565 Ret.BucketsBase = Ret.CUsBase + Hdr.CompUnitCount * DwarfSize +
566 Hdr.LocalTypeUnitCount * DwarfSize +
567 Hdr.ForeignTypeUnitCount * 8;
568 Ret.HashesBase = Ret.BucketsBase + Hdr.BucketCount * 4;
570 Ret.HashesBase + (Hdr.BucketCount > 0 ? Hdr.NameCount * 4 : 0);
571 Ret.EntryOffsetsBase = Ret.StringOffsetsBase + Hdr.NameCount * DwarfSize;
572 Ret.EntriesBase =
573 Ret.EntryOffsetsBase + Hdr.NameCount * DwarfSize + Hdr.AbbrevTableSize;
574 return Ret;
575}
576
578 const DWARFDataExtractor &AS = Section.AccelSection;
579 uint64_t EndOfHeaderOffset = Base;
580 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
581 return E;
582
583 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
584 Offsets = dwarf::findDebugNamesOffsets(EndOfHeaderOffset, Hdr);
585
587 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
588
589 if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
591 "Section too small: cannot read abbreviations.");
592
593 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
594
595 for (;;) {
596 auto AbbrevOr = extractAbbrev(&Offset);
597 if (!AbbrevOr)
598 return AbbrevOr.takeError();
599 if (isSentinel(*AbbrevOr))
600 return Error::success();
601
602 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
604 "Duplicate abbreviation code.");
605 }
606}
607
608DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
609 : NameIdx(&NameIdx), Abbr(&Abbr) {
610 // This merely creates form values. It is up to the caller
611 // (NameIndex::getEntry) to populate them.
612 Values.reserve(Abbr.Attributes.size());
613 for (const auto &Attr : Abbr.Attributes)
614 Values.emplace_back(Attr.Form);
615}
616
617std::optional<DWARFFormValue>
619 assert(Abbr->Attributes.size() == Values.size());
620 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
621 if (std::get<0>(Tuple).Index == Index)
622 return std::get<1>(Tuple);
623 }
624 return std::nullopt;
625}
626
628 return lookup(dwarf::DW_IDX_parent).has_value();
629}
630
631std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
632 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
633 return Off->getAsReferenceUVal();
634 return std::nullopt;
635}
636
637std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
638 // Return the DW_IDX_compile_unit attribute value if it is specified.
639 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
640 return Off->getAsUnsignedConstant();
641 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
642 // implicitly refer to the single CU.
643 if (NameIdx->getCUCount() == 1)
644 return 0;
645 return std::nullopt;
646}
647
648std::optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
649 // Return the DW_IDX_compile_unit attribute value but only if we don't have a
650 // DW_IDX_type_unit attribute. Use Entry::getRelatedCUIndex() to get the
651 // associated CU index if this behaviour is not desired.
652 if (lookup(dwarf::DW_IDX_type_unit).has_value())
653 return std::nullopt;
654 return getRelatedCUIndex();
655}
656
657std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
658 std::optional<uint64_t> Index = getCUIndex();
659 if (!Index || *Index >= NameIdx->getCUCount())
660 return std::nullopt;
661 return NameIdx->getCUOffset(*Index);
662}
663
664std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
665 std::optional<uint64_t> Index = getRelatedCUIndex();
666 if (!Index || *Index >= NameIdx->getCUCount())
667 return std::nullopt;
668 return NameIdx->getCUOffset(*Index);
669}
670
671std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
672 std::optional<uint64_t> Index = getTUIndex();
673 if (!Index || *Index >= NameIdx->getLocalTUCount())
674 return std::nullopt;
675 return NameIdx->getLocalTUOffset(*Index);
676}
677
678std::optional<uint64_t>
680 std::optional<uint64_t> Index = getTUIndex();
681 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
682 if (!Index || *Index < NumLocalTUs)
683 return std::nullopt; // Invalid TU index or TU index is for a local TU
684 // The foreign TU index is the TU index minus the number of local TUs.
685 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
686 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
687 return std::nullopt; // Invalid foreign TU index.
688 return NameIdx->getForeignTUSignature(ForeignTUIndex);
689}
690
691std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
692 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
693 return Off->getAsUnsignedConstant();
694 return std::nullopt;
695}
696
699 // The offset of the accelerator table entry for the parent.
700 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
701 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
702
703 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
704 return std::nullopt;
705 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
706}
707
709 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
711 if (!ParentEntry) {
712 W.getOStream() << "<invalid offset data>";
713 consumeError(ParentEntry.takeError());
714 return;
715 }
716
717 if (!ParentEntry->has_value()) {
718 W.getOStream() << "<parent not indexed>";
719 return;
720 }
721
722 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
723 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
724}
725
727 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
728 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
729 assert(Abbr->Attributes.size() == Values.size());
730 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
731 auto Index = std::get<0>(Tuple).Index;
732 W.startLine() << formatv("{0}: ", Index);
733
734 auto FormValue = std::get<1>(Tuple);
735 if (Index == dwarf::Index::DW_IDX_parent)
736 dumpParentIdx(W, FormValue);
737 else
738 FormValue.dump(W.getOStream());
739 W.getOStream() << '\n';
740 }
741}
742
747
749 assert(CU < Hdr.CompUnitCount);
750 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
751 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
752 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
753}
754
756 assert(TU < Hdr.LocalTypeUnitCount);
757 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
759 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
760 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
761}
762
764 assert(TU < Hdr.ForeignTypeUnitCount);
765 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
767 Offsets.CUsBase +
768 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
769 return Section.AccelSection.getU64(&Offset);
770}
771
774 const DWARFDataExtractor &AS = Section.AccelSection;
775 if (!AS.isValidOffset(*Offset))
777 "Incorrectly terminated entry list.");
778
779 uint32_t AbbrevCode = AS.getULEB128(Offset);
780 if (AbbrevCode == 0)
782
783 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
784 if (AbbrevIt == Abbrevs.end())
785 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
786
787 Entry E(*this, *AbbrevIt);
788
789 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
790 for (auto &Value : E.Values) {
791 if (!Value.extractValue(AS, Offset, FormParams))
793 "Error extracting index attribute values.");
794 }
795 return std::move(E);
796}
797
800 assert(0 < Index && Index <= Hdr.NameCount);
801 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
802 uint64_t StringOffsetOffset =
803 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
804 uint64_t EntryOffsetOffset =
805 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
806 const DWARFDataExtractor &AS = Section.AccelSection;
807
808 uint64_t StringOffset =
809 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
810 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
811 EntryOffset += Offsets.EntriesBase;
812 return {Section.StringSection, Index, StringOffset, EntryOffset};
813}
814
817 assert(Bucket < Hdr.BucketCount);
818 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
819 return Section.AccelSection.getU32(&BucketOffset);
820}
821
823 assert(0 < Index && Index <= Hdr.NameCount);
824 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
825 return Section.AccelSection.getU32(&HashOffset);
826}
827
828// Returns true if we should continue scanning for entries, false if this is the
829// last (sentinel) entry). In case of a parsing error we also return false, as
830// it's not possible to recover this entry list (but the other lists may still
831// parse OK).
832bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
833 uint64_t *Offset) const {
834 uint64_t EntryId = *Offset;
835 auto EntryOr = getEntry(Offset);
836 if (!EntryOr) {
837 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
838 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
839 return false;
840 }
841
842 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
843 EntryOr->dump(W);
844 return true;
845}
846
847void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
848 const NameTableEntry &NTE,
849 std::optional<uint32_t> Hash) const {
850 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
851 if (Hash)
852 W.printHex("Hash", *Hash);
853
854 W.startLine() << formatv("String: {0:x8}", NTE.getStringOffset());
855 W.getOStream() << " \"" << NTE.getString() << "\"\n";
856
857 uint64_t EntryOffset = NTE.getEntryOffset();
858 while (dumpEntry(W, &EntryOffset))
859 /*empty*/;
860}
861
862void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
863 ListScope CUScope(W, "Compilation Unit offsets");
864 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
865 W.startLine() << formatv("CU[{0}]: {1:x8}\n", CU, getCUOffset(CU));
866}
867
868void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
869 if (Hdr.LocalTypeUnitCount == 0)
870 return;
871
872 ListScope TUScope(W, "Local Type Unit offsets");
873 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
874 W.startLine() << formatv("LocalTU[{0}]: {1:x8}\n", TU,
875 getLocalTUOffset(TU));
876}
877
878void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
879 if (Hdr.ForeignTypeUnitCount == 0)
880 return;
881
882 ListScope TUScope(W, "Foreign Type Unit signatures");
883 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
884 W.startLine() << formatv("ForeignTU[{0}]: {1:x16}\n", TU,
885 getForeignTUSignature(TU));
886 }
887}
888
889void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
890 ListScope AbbrevsScope(W, "Abbreviations");
891 std::vector<const Abbrev *> AbbrevsVect;
892 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
893 AbbrevsVect.push_back(&Abbr);
894 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
895 return LHS->AbbrevOffset < RHS->AbbrevOffset;
896 });
897 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
898 Abbr->dump(W);
899}
900
901void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
902 uint32_t Bucket) const {
903 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
904 uint32_t Index = getBucketArrayEntry(Bucket);
905 if (Index == 0) {
906 W.printString("EMPTY");
907 return;
908 }
909 if (Index > Hdr.NameCount) {
910 W.printString("Name index is invalid");
911 return;
912 }
913
914 for (; Index <= Hdr.NameCount; ++Index) {
915 uint32_t Hash = getHashArrayEntry(Index);
916 if (Hash % Hdr.BucketCount != Bucket)
917 break;
918
919 dumpName(W, getNameTableEntry(Index), Hash);
920 }
921}
922
924 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
925 Hdr.dump(W);
926 dumpCUs(W);
927 dumpLocalTUs(W);
928 dumpForeignTUs(W);
929 dumpAbbreviations(W);
930
931 if (Hdr.BucketCount > 0) {
932 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
933 dumpBucket(W, Bucket);
934 return;
935 }
936
937 W.startLine() << "Hash table not present\n";
938 for (const NameTableEntry &NTE : *this)
939 dumpName(W, NTE, std::nullopt);
940}
941
943 uint64_t Offset = 0;
944 while (AccelSection.isValidOffset(Offset)) {
945 NameIndex Next(*this, Offset);
946 if (Error E = Next.extract())
947 return E;
948 Offset = Next.getNextUnitOffset();
949 NameIndices.push_back(std::move(Next));
950 }
951 return Error::success();
952}
953
958
960 ScopedPrinter W(OS);
961 for (const NameIndex &NI : NameIndices)
962 NI.dump(W);
963}
964
965std::optional<uint64_t>
966DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
967 const Header &Hdr = CurrentIndex->Hdr;
968 if (Hdr.BucketCount == 0) {
969 // No Hash Table, We need to search through all names in the Name Index.
970 for (const NameTableEntry &NTE : *CurrentIndex) {
971 if (NTE.sameNameAs(Key))
972 return NTE.getEntryOffset();
973 }
974 return std::nullopt;
975 }
976
977 // The Name Index has a Hash Table, so use that to speed up the search.
978 // Compute the Key Hash, if it has not been done already.
979 if (!Hash)
980 Hash = caseFoldingDjbHash(Key);
981 uint32_t Bucket = *Hash % Hdr.BucketCount;
982 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
983 if (Index == 0)
984 return std::nullopt; // Empty bucket
985
986 for (; Index <= Hdr.NameCount; ++Index) {
987 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
988 if (HashAtIndex % Hdr.BucketCount != Bucket)
989 return std::nullopt; // End of bucket
990 // Only compare names if the hashes match.
991 if (HashAtIndex != Hash)
992 continue;
993
994 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
995 if (NTE.sameNameAs(Key))
996 return NTE.getEntryOffset();
997 }
998 return std::nullopt;
999}
1000
1001bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
1002 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
1003 if (!EntryOr) {
1004 consumeError(EntryOr.takeError());
1005 return false;
1006 }
1007 CurrentEntry = std::move(*EntryOr);
1008 return true;
1009}
1010
1011bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1012 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1013 if (!Offset)
1014 return false;
1015 DataOffset = *Offset;
1016 return getEntryAtCurrentOffset();
1017}
1018
1019void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1020 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1021 CurrentIndex != End; ++CurrentIndex) {
1022 if (findInCurrentIndex())
1023 return;
1024 }
1025 setEnd();
1026}
1027
1028void DWARFDebugNames::ValueIterator::next() {
1029 assert(CurrentIndex && "Incrementing an end() iterator?");
1030
1031 // First try the next entry in the current Index.
1032 if (getEntryAtCurrentOffset())
1033 return;
1034
1035 // If we're a local iterator or we have reached the last Index, we're done.
1036 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1037 setEnd();
1038 return;
1039 }
1040
1041 // Otherwise, try the next index.
1042 ++CurrentIndex;
1043 searchFromStartOfCurrentIndex();
1044}
1045
1047 StringRef Key)
1048 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1049 Key(std::string(Key)) {
1050 searchFromStartOfCurrentIndex();
1051}
1052
1055 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1056 if (!findInCurrentIndex())
1057 setEnd();
1058}
1059
1062 if (NameIndices.empty())
1064 return make_range(ValueIterator(*this, Key), ValueIterator());
1065}
1066
1069 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
1070 for (const auto &NI : *this) {
1071 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1072 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1073 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
1074 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
1075 }
1076 }
1077 return UnitOffsetToNameIndex.lookup(UnitOffset);
1078}
1079
1080static bool isObjCSelector(StringRef Name) {
1081 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1082 (Name[1] == '[');
1083}
1084
1085std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1086 if (!isObjCSelector(Name))
1087 return std::nullopt;
1088 // "-[Atom setMass:]"
1089 StringRef ClassNameStart(Name.drop_front(2));
1090 size_t FirstSpace = ClassNameStart.find(' ');
1091 if (FirstSpace == StringRef::npos)
1092 return std::nullopt;
1093
1094 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1095 if (!SelectorStart.size())
1096 return std::nullopt;
1097
1099 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1100 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1101
1102 // "-[Class(Category) selector :withArg ...]"
1103 if (Ans.ClassName.back() == ')') {
1104 size_t OpenParens = Ans.ClassName.find('(');
1105 if (OpenParens != StringRef::npos) {
1106 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1107
1108 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1109 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1110 // does it this way.
1111 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1112 }
1113 }
1114 return Ans;
1115}
1116
1117std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
1118 // We are looking for template parameters to strip from Name. e.g.
1119 //
1120 // operator<<B>
1121 //
1122 // We look for > at the end but if it does not contain any < then we
1123 // have something like operator>>. We check for the operator<=> case.
1124 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1125 return {};
1126
1127 // How many < until we have the start of the template parameters.
1128 size_t NumLeftAnglesToSkip = 1;
1129
1130 // If we have operator<=> then we need to skip its < as well.
1131 NumLeftAnglesToSkip += Name.count("<=>");
1132
1133 size_t RightAngleCount = Name.count('>');
1134 size_t LeftAngleCount = Name.count('<');
1135
1136 // If we have more < than > we have operator< or operator<<
1137 // we to account for their < as well.
1138 if (LeftAngleCount > RightAngleCount)
1139 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1140
1141 size_t StartOfTemplate = 0;
1142 while (NumLeftAnglesToSkip--)
1143 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1144
1145 StringRef Result = Name.substr(0, StartOfTemplate - 1);
1146 if (Result.empty())
1147 return std::nullopt;
1148 return Result;
1149}
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:661
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, GsymDataExtractor &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...
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static constexpr size_t npos
Definition StringRef.h:58
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:629
char back() const
Get the last character in the string.
Definition StringRef.h:153
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
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:600
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:636
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:837
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1047
@ 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:928
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:950
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1109
@ DW_ATOM_type_flags
Definition Dwarf.h:950
@ DW_ATOM_die_tag
Definition Dwarf.h:949
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition Dwarf.h:946
@ DW_ATOM_cu_offset
Definition Dwarf.h:947
NodeAddr< CodeNode * > Code
Definition RDFGraph.h:388
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
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:840
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:1013
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:94
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:2207
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ 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:334
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:853
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
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...
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:221
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
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:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:861
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:1122