LLVM 24.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"
19#include <cstddef>
20#include <cstdint>
21#include <utility>
22
23using namespace llvm;
24
25namespace {
26struct Atom {
27 unsigned Value;
28};
29
30static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
32 if (!Str.empty())
33 return OS << Str;
34 return OS << "DW_ATOM_unknown_" << formatv("{0:x-}", A.Value);
35}
36} // namespace
37
38static Atom formatAtom(unsigned Atom) { return {Atom}; }
39
41
43 uint64_t Offset = 0;
44
45 // Check that we can at least read the header.
46 if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4))
48 "Section too small: cannot read header.");
49
50 Hdr.Magic = AccelSection.getU32(&Offset);
51 Hdr.Version = AccelSection.getU16(&Offset);
52 Hdr.HashFunction = AccelSection.getU16(&Offset);
53 Hdr.BucketCount = AccelSection.getU32(&Offset);
54 Hdr.HashCount = AccelSection.getU32(&Offset);
55 Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
56 FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
57
58 // Check that we can read all the hashes and offsets from the
59 // section (see SourceLevelDebugging.md for the structure of the index).
60 if (!AccelSection.isValidOffset(getIthBucketBase(Hdr.BucketCount - 1)))
61 return createStringError(
63 "Section too small: cannot read buckets and hashes.");
64
65 HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
66 uint32_t NumAtoms = AccelSection.getU32(&Offset);
67
68 HashDataEntryLength = 0;
69 auto MakeUnsupportedFormError = [](dwarf::Form Form) {
71 "Unsupported form:" +
73 };
74
75 for (unsigned i = 0; i < NumAtoms; ++i) {
76 uint16_t AtomType = AccelSection.getU16(&Offset);
77 auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
78 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
79
80 std::optional<uint8_t> FormSize =
81 dwarf::getFixedFormByteSize(AtomForm, FormParams);
82 if (!FormSize)
83 return MakeUnsupportedFormError(AtomForm);
84 HashDataEntryLength += *FormSize;
85 }
86
87 IsValid = true;
88 return Error::success();
89}
90
92 return Hdr.BucketCount;
93}
94uint32_t AppleAcceleratorTable::getNumHashes() const { return Hdr.HashCount; }
95uint32_t AppleAcceleratorTable::getSizeHdr() const { return sizeof(Hdr); }
97 return Hdr.HeaderDataLength;
98}
99
100ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
101 AppleAcceleratorTable::HeaderData::Form>>
103 return HdrData.Atoms;
104}
105
107 for (auto Atom : getAtomsDesc()) {
108 DWARFFormValue FormValue(Atom.second);
109 switch (Atom.first) {
113 if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
115 FormValue.getForm() == dwarf::DW_FORM_sdata)
116 return false;
117 break;
118 default:
119 break;
120 }
121 }
122 return true;
123}
124
125std::pair<uint64_t, dwarf::Tag>
126AppleAcceleratorTable::readAtoms(uint64_t *HashDataOffset) {
127 uint64_t DieOffset = dwarf::DW_INVALID_OFFSET;
128 dwarf::Tag DieTag = dwarf::DW_TAG_null;
129
130 for (auto Atom : getAtomsDesc()) {
131 DWARFFormValue FormValue(Atom.second);
132 FormValue.extractValue(AccelSection, HashDataOffset, FormParams);
133 switch (Atom.first) {
135 DieOffset = *FormValue.getAsUnsignedConstant();
136 break;
138 DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
139 break;
140 default:
141 break;
142 }
143 }
144 return {DieOffset, DieTag};
145}
146
147void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
148 DictScope HeaderScope(W, "Header");
149 W.printHex("Magic", Magic);
150 W.printHex("Version", Version);
151 W.printHex("Hash function", HashFunction);
152 W.printNumber("Bucket count", BucketCount);
153 W.printNumber("Hashes count", HashCount);
154 W.printNumber("HeaderData length", HeaderDataLength);
155}
156
157std::optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
158 std::optional<DWARFFormValue> Value) const {
159 if (!Value)
160 return std::nullopt;
161
162 switch (Value->getForm()) {
163 case dwarf::DW_FORM_ref1:
164 case dwarf::DW_FORM_ref2:
165 case dwarf::DW_FORM_ref4:
166 case dwarf::DW_FORM_ref8:
167 case dwarf::DW_FORM_ref_udata:
168 return Value->getRawUValue() + DIEOffsetBase;
169 default:
170 return Value->getAsSectionOffset();
171 }
172}
173
174bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
175 SmallVectorImpl<DWARFFormValue> &AtomForms,
176 uint64_t *DataOffset) const {
177 uint64_t NameOffset = *DataOffset;
178 if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
179 W.printString("Incorrectly terminated list.");
180 return false;
181 }
182 uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
183 if (!StringOffset)
184 return false; // End of list
185
186 DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
187 W.startLine() << formatv("String: {0:x8}", StringOffset);
188 W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";
189
190 unsigned NumData = AccelSection.getU32(DataOffset);
191 for (unsigned Data = 0; Data < NumData; ++Data) {
192 ListScope DataScope(W, ("Data " + Twine(Data)).str());
193 unsigned i = 0;
194 for (auto &Atom : AtomForms) {
195 W.startLine() << formatv("Atom[{0}]: ", i);
196 if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
197 Atom.dump(W.getOStream());
198 if (std::optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
199 StringRef Str = dwarf::AtomValueString(HdrData.Atoms[i].first, *Val);
200 if (!Str.empty())
201 W.getOStream() << " (" << Str << ")";
202 }
203 } else
204 W.getOStream() << "Error extracting the value";
205 W.getOStream() << "\n";
206 i++;
207 }
208 }
209 return true; // more entries follow
210}
211
213 if (!IsValid)
214 return;
215
216 ScopedPrinter W(OS);
217
218 Hdr.dump(W);
219
220 W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
221 W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
222 W.printNumber("Size of each hash data entry", getHashDataEntryLength());
224 {
225 ListScope AtomsScope(W, "Atoms");
226 unsigned i = 0;
227 for (const auto &Atom : HdrData.Atoms) {
228 DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
229 W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
230 W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
231 AtomForms.push_back(DWARFFormValue(Atom.second));
232 }
233 }
234
235 // Now go through the actual tables and dump them.
236 uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
237 uint64_t HashesBase = Offset + Hdr.BucketCount * 4;
238 uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;
239
240 for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
241 unsigned Index = AccelSection.getU32(&Offset);
242
243 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
244 if (Index == UINT32_MAX) {
245 W.printString("EMPTY");
246 continue;
247 }
248
249 for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
250 uint64_t HashOffset = HashesBase + HashIdx*4;
251 uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
252 uint32_t Hash = AccelSection.getU32(&HashOffset);
253
254 if (Hash % Hdr.BucketCount != Bucket)
255 break;
256
257 uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset);
258 ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str());
259 if (!AccelSection.isValidOffset(DataOffset)) {
260 W.printString("Invalid section offset");
261 continue;
262 }
263 while (dumpName(W, AtomForms, &DataOffset))
264 /*empty*/;
265 }
266 }
267}
268
270 : Table(Table) {
271 Values.reserve(Table.HdrData.Atoms.size());
272 for (const auto &Atom : Table.HdrData.Atoms)
273 Values.push_back(DWARFFormValue(Atom.second));
274}
275
276void AppleAcceleratorTable::Entry::extract(uint64_t *Offset) {
277 for (auto &FormValue : Values)
278 FormValue.extractValue(Table.AccelSection, Offset, Table.FormParams);
279}
280
281std::optional<DWARFFormValue>
282AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType AtomToFind) const {
283 for (auto [Atom, FormValue] : zip_equal(Table.HdrData.Atoms, Values))
284 if (Atom.first == AtomToFind)
285 return FormValue;
286 return std::nullopt;
287}
288
289std::optional<uint64_t>
291 return Table.HdrData.extractOffset(lookup(dwarf::DW_ATOM_die_offset));
292}
293
294std::optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
295 return Table.HdrData.extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
296}
297
298std::optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
299 std::optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
300 if (!Tag)
301 return std::nullopt;
302 if (std::optional<uint64_t> Value = Tag->getAsUnsignedConstant())
303 return dwarf::Tag(*Value);
304 return std::nullopt;
305}
306
308 const AppleAcceleratorTable &AccelTable, uint64_t DataOffset)
309 : Current(AccelTable), Offset(DataOffset) {}
310
311void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() {
312 if (NumEntriesToCome == 0)
313 prepareNextStringOrEnd();
314 if (isEnd())
315 return;
316 uint64_t OffsetCopy = Offset;
317 Current.BaseEntry.extract(&OffsetCopy);
318 NumEntriesToCome--;
319 Offset += getTable().getHashDataEntryLength();
320}
321
322void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() {
323 const AppleAcceleratorTable &Table = getTable();
324 if (Offset == 0) {
325 // Always start looking for strings using a valid offset from the Offsets
326 // table. Entries are not always consecutive.
327 std::optional<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);
328 if (!OptOffset)
329 return setToEnd();
330 Offset = *OptOffset;
331 }
332 std::optional<uint32_t> StrOffset = Table.readStringOffsetAt(Offset);
333 if (!StrOffset)
334 return setToEnd();
335
336 // A zero denotes the end of the collision list. Skip to the next offset
337 // in the offsets table by setting the Offset to zero so we will grab the
338 // next offset from the offsets table.
339 if (*StrOffset == 0) {
340 Offset = 0;
341 return prepareNextStringOrEnd();
342 }
343 Current.StrOffset = *StrOffset;
344
345 std::optional<uint32_t> MaybeNumEntries = Table.readU32FromAccel(Offset);
346 if (!MaybeNumEntries || *MaybeNumEntries == 0)
347 return setToEnd();
348 NumEntriesToCome = *MaybeNumEntries;
349}
350
352 bool SetEnd)
353 : Current(Table), Offset(0), NumEntriesToCome(0) {
354 if (SetEnd)
355 setToEnd();
356 else
357 prepareNextEntryOrEnd();
358}
359
362 const auto EmptyRange =
363 make_range(SameNameIterator(*this, 0), SameNameIterator(*this, 0));
364 if (!IsValid)
365 return EmptyRange;
366
367 // Find the bucket.
368 uint32_t SearchHash = djbHash(Key);
369 uint32_t BucketIdx = hashToBucketIdx(SearchHash);
370 std::optional<uint32_t> HashIdx = idxOfHashInBucket(SearchHash, BucketIdx);
371 if (!HashIdx)
372 return EmptyRange;
373
374 std::optional<uint64_t> MaybeDataOffset = readIthOffset(*HashIdx);
375 if (!MaybeDataOffset)
376 return EmptyRange;
377
378 uint64_t DataOffset = *MaybeDataOffset;
379 if (DataOffset >= AccelSection.size())
380 return EmptyRange;
381
382 std::optional<uint32_t> StrOffset = readStringOffsetAt(DataOffset);
383 // Valid input and still have strings in this hash.
384 while (StrOffset && *StrOffset) {
385 std::optional<StringRef> MaybeStr = readStringFromStrSection(*StrOffset);
386 std::optional<uint32_t> NumEntries = this->readU32FromAccel(DataOffset);
387 if (!MaybeStr || !NumEntries)
388 return EmptyRange;
389 uint64_t EndOffset = DataOffset + *NumEntries * getHashDataEntryLength();
390 if (Key == *MaybeStr)
391 return make_range({*this, DataOffset},
392 SameNameIterator{*this, EndOffset});
393 DataOffset = EndOffset;
394 StrOffset = readStringOffsetAt(DataOffset);
395 }
396
397 return EmptyRange;
398}
399
400std::optional<uint32_t>
401AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,
402 uint32_t BucketIdx) const {
403 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);
404 if (!HashStartIdx)
405 return std::nullopt;
406
407 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {
408 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);
409 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))
410 break;
411 if (*MaybeHash == HashToFind)
412 return HashIdx;
413 }
414 return std::nullopt;
415}
416
417std::optional<StringRef> AppleAcceleratorTable::readStringFromStrSection(
418 uint64_t StringSectionOffset) const {
420 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);
421 if (E) {
422 consumeError(std::move(E));
423 return std::nullopt;
424 }
425 return Str;
426}
427
428std::optional<uint32_t>
429AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,
430 bool UseRelocation) const {
432 uint32_t Data = UseRelocation
433 ? AccelSection.getRelocatedValue(4, &Offset, nullptr, &E)
434 : AccelSection.getU32(&Offset, &E);
435 if (E) {
436 consumeError(std::move(E));
437 return std::nullopt;
438 }
439 return Data;
440}
441
443 DictScope HeaderScope(W, "Header");
444 W.printHex("Length", UnitLength);
445 W.printString("Format", dwarf::FormatString(Format));
446 W.printNumber("Version", Version);
447 W.printNumber("CU count", CompUnitCount);
448 W.printNumber("Local TU count", LocalTypeUnitCount);
449 W.printNumber("Foreign TU count", ForeignTypeUnitCount);
450 W.printNumber("Bucket count", BucketCount);
451 W.printNumber("Name count", NameCount);
452 W.printHex("Abbreviations table size", AbbrevTableSize);
453 W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
454}
455
457 uint64_t *Offset) {
458 auto HeaderError = [Offset = *Offset](Error E) {
460 "parsing .debug_names header at 0x%" PRIx64 ": %s",
461 Offset, toString(std::move(E)).c_str());
462 };
463
465 std::tie(UnitLength, Format) = AS.getInitialLength(C);
466
467 Version = AS.getU16(C);
468 AS.skip(C, 2); // padding
469 CompUnitCount = AS.getU32(C);
472 BucketCount = AS.getU32(C);
473 NameCount = AS.getU32(C);
476
477 if (!C)
478 return HeaderError(C.takeError());
479
482 "cannot read header augmentation"));
484 AS.getU8(C, reinterpret_cast<uint8_t *>(AugmentationString.data()),
486 *Offset = C.tell();
487 return C.takeError();
488}
489
491 DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
492 W.startLine() << formatv("Tag: {0}\n", Tag);
493
494 for (const auto &Attr : Attributes)
495 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
496}
497
499 return {dwarf::Index(0), dwarf::Form(0)};
500}
501
503 return AE == sentinelAttrEnc();
504}
505
509
510static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
511 return Abbr.Code == 0;
512}
513
514Expected<DWARFDebugNames::AttributeEncoding>
515DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
516 if (*Offset >= Offsets.EntriesBase) {
518 "Incorrectly terminated abbreviation table.");
519 }
520
521 uint32_t Index = Section.AccelSection.getULEB128(Offset);
522 uint32_t Form = Section.AccelSection.getULEB128(Offset);
523 return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
524}
525
526Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
527DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
528 std::vector<AttributeEncoding> Result;
529 for (;;) {
530 auto AttrEncOr = extractAttributeEncoding(Offset);
531 if (!AttrEncOr)
532 return AttrEncOr.takeError();
533 if (isSentinel(*AttrEncOr))
534 return std::move(Result);
535
536 Result.emplace_back(*AttrEncOr);
537 }
538}
539
540Expected<DWARFDebugNames::Abbrev>
541DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
542 if (*Offset >= Offsets.EntriesBase) {
544 "Incorrectly terminated abbreviation table.");
545 }
546 const uint64_t AbbrevOffset = *Offset;
547 uint32_t Code = Section.AccelSection.getULEB128(Offset);
548 if (Code == 0)
549 return sentinelAbbrev();
550
551 uint32_t Tag = Section.AccelSection.getULEB128(Offset);
552 auto AttrEncOr = extractAttributeEncodings(Offset);
553 if (!AttrEncOr)
554 return AttrEncOr.takeError();
555 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
556}
557
558DWARFDebugNames::DWARFDebugNamesOffsets
559dwarf::findDebugNamesOffsets(uint64_t EndOfHeaderOffset,
560 const DWARFDebugNames::Header &Hdr) {
561 uint64_t DwarfSize = getDwarfOffsetByteSize(Hdr.Format);
563 Ret.CUsBase = EndOfHeaderOffset;
564 Ret.BucketsBase = Ret.CUsBase + Hdr.CompUnitCount * DwarfSize +
565 Hdr.LocalTypeUnitCount * DwarfSize +
566 Hdr.ForeignTypeUnitCount * 8;
567 Ret.HashesBase = Ret.BucketsBase + Hdr.BucketCount * 4;
569 Ret.HashesBase + (Hdr.BucketCount > 0 ? Hdr.NameCount * 4 : 0);
570 Ret.EntryOffsetsBase = Ret.StringOffsetsBase + Hdr.NameCount * DwarfSize;
571 Ret.EntriesBase =
572 Ret.EntryOffsetsBase + Hdr.NameCount * DwarfSize + Hdr.AbbrevTableSize;
573 return Ret;
574}
575
577 const DWARFDataExtractor &AS = Section.AccelSection;
578 uint64_t EndOfHeaderOffset = Base;
579 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
580 return E;
581
582 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
583 Offsets = dwarf::findDebugNamesOffsets(EndOfHeaderOffset, Hdr);
584
585 uint64_t Offset =
586 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
587
588 if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
590 "Section too small: cannot read abbreviations.");
591
592 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
593
594 for (;;) {
595 auto AbbrevOr = extractAbbrev(&Offset);
596 if (!AbbrevOr)
597 return AbbrevOr.takeError();
598 if (isSentinel(*AbbrevOr))
599 return Error::success();
600
601 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
603 "Duplicate abbreviation code.");
604 }
605}
606
607DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
608 : NameIdx(&NameIdx), Abbr(&Abbr) {
609 // This merely creates form values. It is up to the caller
610 // (NameIndex::getEntry) to populate them.
611 Values.reserve(Abbr.Attributes.size());
612 for (const auto &Attr : Abbr.Attributes)
613 Values.emplace_back(Attr.Form);
614}
615
616std::optional<DWARFFormValue>
618 assert(Abbr->Attributes.size() == Values.size());
619 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
620 if (std::get<0>(Tuple).Index == Index)
621 return std::get<1>(Tuple);
622 }
623 return std::nullopt;
624}
625
627 return lookup(dwarf::DW_IDX_parent).has_value();
628}
629
630std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
631 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
632 return Off->getAsReferenceUVal();
633 return std::nullopt;
634}
635
636std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
637 // Return the DW_IDX_compile_unit attribute value if it is specified.
638 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
639 return Off->getAsUnsignedConstant();
640 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
641 // implicitly refer to the single CU.
642 if (NameIdx->getCUCount() == 1)
643 return 0;
644 return std::nullopt;
645}
646
647std::optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
648 // Return the DW_IDX_compile_unit attribute value but only if we don't have a
649 // DW_IDX_type_unit attribute. Use Entry::getRelatedCUIndex() to get the
650 // associated CU index if this behaviour is not desired.
651 if (lookup(dwarf::DW_IDX_type_unit).has_value())
652 return std::nullopt;
653 return getRelatedCUIndex();
654}
655
656std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
657 std::optional<uint64_t> Index = getCUIndex();
658 if (!Index || *Index >= NameIdx->getCUCount())
659 return std::nullopt;
660 return NameIdx->getCUOffset(*Index);
661}
662
663std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
664 std::optional<uint64_t> Index = getRelatedCUIndex();
665 if (!Index || *Index >= NameIdx->getCUCount())
666 return std::nullopt;
667 return NameIdx->getCUOffset(*Index);
668}
669
670std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
671 std::optional<uint64_t> Index = getTUIndex();
672 if (!Index || *Index >= NameIdx->getLocalTUCount())
673 return std::nullopt;
674 return NameIdx->getLocalTUOffset(*Index);
675}
676
677std::optional<uint64_t>
679 std::optional<uint64_t> Index = getTUIndex();
680 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
681 if (!Index || *Index < NumLocalTUs)
682 return std::nullopt; // Invalid TU index or TU index is for a local TU
683 // The foreign TU index is the TU index minus the number of local TUs.
684 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
685 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
686 return std::nullopt; // Invalid foreign TU index.
687 return NameIdx->getForeignTUSignature(ForeignTUIndex);
688}
689
690std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
691 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
692 return Off->getAsUnsignedConstant();
693 return std::nullopt;
694}
695
698 // The offset of the accelerator table entry for the parent.
699 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
700 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
701
702 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
703 return std::nullopt;
704 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
705}
706
708 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
710 if (!ParentEntry) {
711 W.getOStream() << "<invalid offset data>";
712 consumeError(ParentEntry.takeError());
713 return;
714 }
715
716 if (!ParentEntry->has_value()) {
717 W.getOStream() << "<parent not indexed>";
718 return;
719 }
720
721 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
722 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
723}
724
726 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
727 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
728 assert(Abbr->Attributes.size() == Values.size());
729 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
730 auto Index = std::get<0>(Tuple).Index;
731 W.startLine() << formatv("{0}: ", Index);
732
733 auto FormValue = std::get<1>(Tuple);
734 if (Index == dwarf::Index::DW_IDX_parent)
735 dumpParentIdx(W, FormValue);
736 else
737 FormValue.dump(W.getOStream());
738 W.getOStream() << '\n';
739 }
740}
741
746
748 assert(CU < Hdr.CompUnitCount);
749 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
750 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
751 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
752}
753
755 assert(TU < Hdr.LocalTypeUnitCount);
756 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
757 uint64_t Offset =
758 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
759 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
760}
761
763 assert(TU < Hdr.ForeignTypeUnitCount);
764 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
765 uint64_t Offset =
766 Offsets.CUsBase +
767 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
768 return Section.AccelSection.getU64(&Offset);
769}
770
773 const DWARFDataExtractor &AS = Section.AccelSection;
774 if (!AS.isValidOffset(*Offset))
776 "Incorrectly terminated entry list.");
777
778 uint32_t AbbrevCode = AS.getULEB128(Offset);
779 if (AbbrevCode == 0)
781
782 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
783 if (AbbrevIt == Abbrevs.end())
784 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
785
786 Entry E(*this, *AbbrevIt);
787
788 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
789 for (auto &Value : E.Values) {
790 if (!Value.extractValue(AS, Offset, FormParams))
792 "Error extracting index attribute values.");
793 }
794 return std::move(E);
795}
796
799 assert(0 < Index && Index <= Hdr.NameCount);
800 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
801 uint64_t StringOffsetOffset =
802 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
803 uint64_t EntryOffsetOffset =
804 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
805 const DWARFDataExtractor &AS = Section.AccelSection;
806
807 uint64_t StringOffset =
808 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
809 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
810 EntryOffset += Offsets.EntriesBase;
811 return {Section.StringSection, Index, StringOffset, EntryOffset};
812}
813
816 assert(Bucket < Hdr.BucketCount);
817 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
818 return Section.AccelSection.getU32(&BucketOffset);
819}
820
822 assert(0 < Index && Index <= Hdr.NameCount);
823 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
824 return Section.AccelSection.getU32(&HashOffset);
825}
826
827// Returns true if we should continue scanning for entries, false if this is the
828// last (sentinel) entry). In case of a parsing error we also return false, as
829// it's not possible to recover this entry list (but the other lists may still
830// parse OK).
831bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
832 uint64_t *Offset) const {
833 uint64_t EntryId = *Offset;
834 auto EntryOr = getEntry(Offset);
835 if (!EntryOr) {
836 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
837 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
838 return false;
839 }
840
841 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
842 EntryOr->dump(W);
843 return true;
844}
845
846void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
847 const NameTableEntry &NTE,
848 std::optional<uint32_t> Hash) const {
849 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
850 if (Hash)
851 W.printHex("Hash", *Hash);
852
853 W.startLine() << formatv("String: {0:x8}", NTE.getStringOffset());
854 W.getOStream() << " \"" << NTE.getString() << "\"\n";
855
856 uint64_t EntryOffset = NTE.getEntryOffset();
857 while (dumpEntry(W, &EntryOffset))
858 /*empty*/;
859}
860
861void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
862 ListScope CUScope(W, "Compilation Unit offsets");
863 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
864 W.startLine() << formatv("CU[{0}]: {1:x8}\n", CU, getCUOffset(CU));
865}
866
867void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
868 if (Hdr.LocalTypeUnitCount == 0)
869 return;
870
871 ListScope TUScope(W, "Local Type Unit offsets");
872 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
873 W.startLine() << formatv("LocalTU[{0}]: {1:x8}\n", TU,
874 getLocalTUOffset(TU));
875}
876
877void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
878 if (Hdr.ForeignTypeUnitCount == 0)
879 return;
880
881 ListScope TUScope(W, "Foreign Type Unit signatures");
882 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
883 W.startLine() << formatv("ForeignTU[{0}]: {1:x16}\n", TU,
884 getForeignTUSignature(TU));
885 }
886}
887
888void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
889 ListScope AbbrevsScope(W, "Abbreviations");
890 std::vector<const Abbrev *> AbbrevsVect;
891 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
892 AbbrevsVect.push_back(&Abbr);
893 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
894 return LHS->AbbrevOffset < RHS->AbbrevOffset;
895 });
896 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
897 Abbr->dump(W);
898}
899
900void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
901 uint32_t Bucket) const {
902 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
903 uint32_t Index = getBucketArrayEntry(Bucket);
904 if (Index == 0) {
905 W.printString("EMPTY");
906 return;
907 }
908 if (Index > Hdr.NameCount) {
909 W.printString("Name index is invalid");
910 return;
911 }
912
913 for (; Index <= Hdr.NameCount; ++Index) {
914 uint32_t Hash = getHashArrayEntry(Index);
915 if (Hash % Hdr.BucketCount != Bucket)
916 break;
917
918 dumpName(W, getNameTableEntry(Index), Hash);
919 }
920}
921
923 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
924 Hdr.dump(W);
925 dumpCUs(W);
926 dumpLocalTUs(W);
927 dumpForeignTUs(W);
928 dumpAbbreviations(W);
929
930 if (Hdr.BucketCount > 0) {
931 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
932 dumpBucket(W, Bucket);
933 return;
934 }
935
936 W.startLine() << "Hash table not present\n";
937 for (const NameTableEntry &NTE : *this)
938 dumpName(W, NTE, std::nullopt);
939}
940
942 uint64_t Offset = 0;
943 while (AccelSection.isValidOffset(Offset)) {
944 NameIndex Next(*this, Offset);
945 if (Error E = Next.extract())
946 return E;
947 Offset = Next.getNextUnitOffset();
948 NameIndices.push_back(std::move(Next));
949 }
950 return Error::success();
951}
952
957
959 ScopedPrinter W(OS);
960 for (const NameIndex &NI : NameIndices)
961 NI.dump(W);
962}
963
964std::optional<uint64_t>
965DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
966 const Header &Hdr = CurrentIndex->Hdr;
967 if (Hdr.BucketCount == 0) {
968 // No Hash Table, We need to search through all names in the Name Index.
969 for (const NameTableEntry &NTE : *CurrentIndex) {
970 if (NTE.sameNameAs(Key))
971 return NTE.getEntryOffset();
972 }
973 return std::nullopt;
974 }
975
976 // The Name Index has a Hash Table, so use that to speed up the search.
977 // Compute the Key Hash, if it has not been done already.
978 if (!Hash)
979 Hash = caseFoldingDjbHash(Key);
980 uint32_t Bucket = *Hash % Hdr.BucketCount;
981 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
982 if (Index == 0)
983 return std::nullopt; // Empty bucket
984
985 for (; Index <= Hdr.NameCount; ++Index) {
986 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
987 if (HashAtIndex % Hdr.BucketCount != Bucket)
988 return std::nullopt; // End of bucket
989 // Only compare names if the hashes match.
990 if (HashAtIndex != Hash)
991 continue;
992
993 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
994 if (NTE.sameNameAs(Key))
995 return NTE.getEntryOffset();
996 }
997 return std::nullopt;
998}
999
1000bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
1001 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
1002 if (!EntryOr) {
1003 consumeError(EntryOr.takeError());
1004 return false;
1005 }
1006 CurrentEntry = std::move(*EntryOr);
1007 return true;
1008}
1009
1010bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1011 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1012 if (!Offset)
1013 return false;
1014 DataOffset = *Offset;
1015 return getEntryAtCurrentOffset();
1016}
1017
1018void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1019 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1020 CurrentIndex != End; ++CurrentIndex) {
1021 if (findInCurrentIndex())
1022 return;
1023 }
1024 setEnd();
1025}
1026
1027void DWARFDebugNames::ValueIterator::next() {
1028 assert(CurrentIndex && "Incrementing an end() iterator?");
1029
1030 // First try the next entry in the current Index.
1031 if (getEntryAtCurrentOffset())
1032 return;
1033
1034 // If we're a local iterator or we have reached the last Index, we're done.
1035 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1036 setEnd();
1037 return;
1038 }
1039
1040 // Otherwise, try the next index.
1041 ++CurrentIndex;
1042 searchFromStartOfCurrentIndex();
1043}
1044
1046 StringRef Key)
1047 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1048 Key(std::string(Key)) {
1049 searchFromStartOfCurrentIndex();
1050}
1051
1054 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1055 if (!findInCurrentIndex())
1056 setEnd();
1057}
1058
1061 if (NameIndices.empty())
1063 return make_range(ValueIterator(*this, Key), ValueIterator());
1064}
1065
1068 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
1069 for (const auto &NI : *this) {
1070 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1071 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1072 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
1073 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
1074 }
1075 }
1076 return UnitOffsetToNameIndex.lookup(UnitOffset);
1077}
1078
1079static bool isObjCSelector(StringRef Name) {
1080 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1081 (Name[1] == '[');
1082}
1083
1084std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1085 if (!isObjCSelector(Name))
1086 return std::nullopt;
1087 // "-[Atom setMass:]"
1088 StringRef ClassNameStart(Name.drop_front(2));
1089 size_t FirstSpace = ClassNameStart.find(' ');
1090 if (FirstSpace == StringRef::npos)
1091 return std::nullopt;
1092
1093 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1094 if (!SelectorStart.size())
1095 return std::nullopt;
1096
1098 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1099 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1100
1101 // "-[Class(Category) selector :withArg ...]"
1102 if (Ans.ClassName.back() == ')') {
1103 size_t OpenParens = Ans.ClassName.find('(');
1104 if (OpenParens != StringRef::npos) {
1105 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1106
1107 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1108 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1109 // does it this way.
1110 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1111 }
1112 }
1113 return Ans;
1114}
1115
1116std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
1117 // We are looking for template parameters to strip from Name. e.g.
1118 //
1119 // operator<<B>
1120 //
1121 // We look for > at the end but if it does not contain any < then we
1122 // have something like operator>>. We check for the operator<=> case.
1123 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1124 return {};
1125
1126 // How many < until we have the start of the template parameters.
1127 size_t NumLeftAnglesToSkip = 1;
1128
1129 // If we have operator<=> then we need to skip its < as well.
1130 NumLeftAnglesToSkip += Name.count("<=>");
1131
1132 size_t RightAngleCount = Name.count('>');
1133 size_t LeftAngleCount = Name.count('<');
1134
1135 // If we have more < than > we have operator< or operator<<
1136 // we to account for their < as well.
1137 if (LeftAngleCount > RightAngleCount)
1138 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1139
1140 size_t StartOfTemplate = 0;
1141 while (NumLeftAnglesToSkip--)
1142 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1143
1144 StringRef Result = Name.substr(0, StartOfTemplate - 1);
1145 if (Result.empty())
1146 return std::nullopt;
1147 return Result;
1148}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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:678
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:635
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:606
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:642
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:852
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1062
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:943
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:965
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1186
@ DW_ATOM_type_flags
Definition Dwarf.h:1027
@ DW_ATOM_die_tag
Definition Dwarf.h:1026
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition Dwarf.h:1023
@ DW_ATOM_cu_offset
Definition Dwarf.h:1024
NodeAddr< CodeNode * > Code
Definition RDFGraph.h:388
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
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:2208
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)
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:1636
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
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
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
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:878
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:1199