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