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 // SameNameIterator terminates on exact offset equality.
390 uint64_t EndOffset =
391 DataOffset + uint64_t(*NumEntries) * getHashDataEntryLength();
392 if (EndOffset > AccelSection.size())
393 return EmptyRange;
394 if (Key == *MaybeStr)
395 return make_range({*this, DataOffset},
396 SameNameIterator{*this, EndOffset});
397 DataOffset = EndOffset;
398 StrOffset = readStringOffsetAt(DataOffset);
399 }
400
401 return EmptyRange;
402}
403
404std::optional<uint32_t>
405AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,
406 uint32_t BucketIdx) const {
407 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);
408 if (!HashStartIdx)
409 return std::nullopt;
410
411 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {
412 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);
413 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))
414 break;
415 if (*MaybeHash == HashToFind)
416 return HashIdx;
417 }
418 return std::nullopt;
419}
420
421std::optional<StringRef> AppleAcceleratorTable::readStringFromStrSection(
422 uint64_t StringSectionOffset) const {
424 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);
425 if (E) {
426 consumeError(std::move(E));
427 return std::nullopt;
428 }
429 return Str;
430}
431
432std::optional<uint32_t>
433AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,
434 bool UseRelocation) const {
436 uint32_t Data = UseRelocation
437 ? AccelSection.getRelocatedValue(4, &Offset, nullptr, &E)
438 : AccelSection.getU32(&Offset, &E);
439 if (E) {
440 consumeError(std::move(E));
441 return std::nullopt;
442 }
443 return Data;
444}
445
447 DictScope HeaderScope(W, "Header");
448 W.printHex("Length", UnitLength);
449 W.printString("Format", dwarf::FormatString(Format));
450 W.printNumber("Version", Version);
451 W.printNumber("CU count", CompUnitCount);
452 W.printNumber("Local TU count", LocalTypeUnitCount);
453 W.printNumber("Foreign TU count", ForeignTypeUnitCount);
454 W.printNumber("Bucket count", BucketCount);
455 W.printNumber("Name count", NameCount);
456 W.printHex("Abbreviations table size", AbbrevTableSize);
457 W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
458}
459
461 uint64_t *Offset) {
462 auto HeaderError = [Offset = *Offset](Error E) {
464 "parsing .debug_names header at 0x%" PRIx64 ": %s",
465 Offset, toString(std::move(E)).c_str());
466 };
467
469 std::tie(UnitLength, Format) = AS.getInitialLength(C);
470
471 Version = AS.getU16(C);
472 AS.skip(C, 2); // padding
473 CompUnitCount = AS.getU32(C);
476 BucketCount = AS.getU32(C);
477 NameCount = AS.getU32(C);
480
481 if (!C)
482 return HeaderError(C.takeError());
483
486 "cannot read header augmentation"));
488 AS.getU8(C, reinterpret_cast<uint8_t *>(AugmentationString.data()),
490 *Offset = C.tell();
491 return C.takeError();
492}
493
495 DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
496 W.startLine() << formatv("Tag: {0}\n", Tag);
497
498 for (const auto &Attr : Attributes)
499 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
500}
501
503 return {dwarf::Index(0), dwarf::Form(0)};
504}
505
507 return AE == sentinelAttrEnc();
508}
509
513
514static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
515 return Abbr.Code == 0;
516}
517
518Expected<DWARFDebugNames::AttributeEncoding>
519DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
520 if (*Offset >= Offsets.EntriesBase) {
522 "Incorrectly terminated abbreviation table.");
523 }
524
525 uint32_t Index = Section.AccelSection.getULEB128(Offset);
526 uint32_t Form = Section.AccelSection.getULEB128(Offset);
527 return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
528}
529
530Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
531DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
532 std::vector<AttributeEncoding> Result;
533 for (;;) {
534 auto AttrEncOr = extractAttributeEncoding(Offset);
535 if (!AttrEncOr)
536 return AttrEncOr.takeError();
537 if (isSentinel(*AttrEncOr))
538 return std::move(Result);
539
540 Result.emplace_back(*AttrEncOr);
541 }
542}
543
544Expected<DWARFDebugNames::Abbrev>
545DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
546 if (*Offset >= Offsets.EntriesBase) {
548 "Incorrectly terminated abbreviation table.");
549 }
550 const uint64_t AbbrevOffset = *Offset;
551 uint32_t Code = Section.AccelSection.getULEB128(Offset);
552 if (Code == 0)
553 return sentinelAbbrev();
554
555 uint32_t Tag = Section.AccelSection.getULEB128(Offset);
556 auto AttrEncOr = extractAttributeEncodings(Offset);
557 if (!AttrEncOr)
558 return AttrEncOr.takeError();
559 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
560}
561
562DWARFDebugNames::DWARFDebugNamesOffsets
563dwarf::findDebugNamesOffsets(uint64_t EndOfHeaderOffset,
564 const DWARFDebugNames::Header &Hdr) {
565 uint64_t DwarfSize = getDwarfOffsetByteSize(Hdr.Format);
567 Ret.CUsBase = EndOfHeaderOffset;
568 Ret.BucketsBase = Ret.CUsBase + Hdr.CompUnitCount * DwarfSize +
569 Hdr.LocalTypeUnitCount * DwarfSize +
570 Hdr.ForeignTypeUnitCount * 8;
571 Ret.HashesBase = Ret.BucketsBase + Hdr.BucketCount * 4;
573 Ret.HashesBase + (Hdr.BucketCount > 0 ? Hdr.NameCount * 4 : 0);
574 Ret.EntryOffsetsBase = Ret.StringOffsetsBase + Hdr.NameCount * DwarfSize;
575 Ret.EntriesBase =
576 Ret.EntryOffsetsBase + Hdr.NameCount * DwarfSize + Hdr.AbbrevTableSize;
577 return Ret;
578}
579
581 const DWARFDataExtractor &AS = Section.AccelSection;
582 uint64_t EndOfHeaderOffset = Base;
583 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
584 return E;
585
586 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
587 Offsets = dwarf::findDebugNamesOffsets(EndOfHeaderOffset, Hdr);
588
589 uint64_t Offset =
590 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
591
592 if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
594 "Section too small: cannot read abbreviations.");
595
596 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
597
598 for (;;) {
599 auto AbbrevOr = extractAbbrev(&Offset);
600 if (!AbbrevOr)
601 return AbbrevOr.takeError();
602 if (isSentinel(*AbbrevOr))
603 return Error::success();
604
605 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
607 "Duplicate abbreviation code.");
608 }
609}
610
611DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
612 : NameIdx(&NameIdx), Abbr(&Abbr) {
613 // This merely creates form values. It is up to the caller
614 // (NameIndex::getEntry) to populate them.
615 Values.reserve(Abbr.Attributes.size());
616 for (const auto &Attr : Abbr.Attributes)
617 Values.emplace_back(Attr.Form);
618}
619
620std::optional<DWARFFormValue>
622 assert(Abbr->Attributes.size() == Values.size());
623 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
624 if (std::get<0>(Tuple).Index == Index)
625 return std::get<1>(Tuple);
626 }
627 return std::nullopt;
628}
629
631 return lookup(dwarf::DW_IDX_parent).has_value();
632}
633
634std::optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
635 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
636 return Off->getAsReferenceUVal();
637 return std::nullopt;
638}
639
640std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
641 // Return the DW_IDX_compile_unit attribute value if it is specified.
642 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
643 return Off->getAsUnsignedConstant();
644 // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
645 // implicitly refer to the single CU.
646 if (NameIdx->getCUCount() == 1)
647 return 0;
648 return std::nullopt;
649}
650
651std::optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
652 // Return the DW_IDX_compile_unit attribute value but only if we don't have a
653 // DW_IDX_type_unit attribute. Use Entry::getRelatedCUIndex() to get the
654 // associated CU index if this behaviour is not desired.
655 if (lookup(dwarf::DW_IDX_type_unit).has_value())
656 return std::nullopt;
657 return getRelatedCUIndex();
658}
659
660std::optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
661 std::optional<uint64_t> Index = getCUIndex();
662 if (!Index || *Index >= NameIdx->getCUCount())
663 return std::nullopt;
664 return NameIdx->getCUOffset(*Index);
665}
666
667std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
668 std::optional<uint64_t> Index = getRelatedCUIndex();
669 if (!Index || *Index >= NameIdx->getCUCount())
670 return std::nullopt;
671 return NameIdx->getCUOffset(*Index);
672}
673
674std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
675 std::optional<uint64_t> Index = getTUIndex();
676 if (!Index || *Index >= NameIdx->getLocalTUCount())
677 return std::nullopt;
678 return NameIdx->getLocalTUOffset(*Index);
679}
680
681std::optional<uint64_t>
683 std::optional<uint64_t> Index = getTUIndex();
684 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
685 if (!Index || *Index < NumLocalTUs)
686 return std::nullopt; // Invalid TU index or TU index is for a local TU
687 // The foreign TU index is the TU index minus the number of local TUs.
688 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
689 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
690 return std::nullopt; // Invalid foreign TU index.
691 return NameIdx->getForeignTUSignature(ForeignTUIndex);
692}
693
694std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
695 if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
696 return Off->getAsUnsignedConstant();
697 return std::nullopt;
698}
699
702 // The offset of the accelerator table entry for the parent.
703 std::optional<DWARFFormValue> ParentEntryOff = lookup(dwarf::DW_IDX_parent);
704 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
705
706 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
707 return std::nullopt;
708 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
709}
710
712 ScopedPrinter &W, const DWARFFormValue &FormValue) const {
714 if (!ParentEntry) {
715 W.getOStream() << "<invalid offset data>";
716 consumeError(ParentEntry.takeError());
717 return;
718 }
719
720 if (!ParentEntry->has_value()) {
721 W.getOStream() << "<parent not indexed>";
722 return;
723 }
724
725 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
726 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
727}
728
730 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
731 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
732 assert(Abbr->Attributes.size() == Values.size());
733 for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
734 auto Index = std::get<0>(Tuple).Index;
735 W.startLine() << formatv("{0}: ", Index);
736
737 auto FormValue = std::get<1>(Tuple);
738 if (Index == dwarf::Index::DW_IDX_parent)
739 dumpParentIdx(W, FormValue);
740 else
741 FormValue.dump(W.getOStream());
742 W.getOStream() << '\n';
743 }
744}
745
750
752 assert(CU < Hdr.CompUnitCount);
753 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
754 uint64_t Offset = Offsets.CUsBase + SectionOffsetSize * CU;
755 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
756}
757
759 assert(TU < Hdr.LocalTypeUnitCount);
760 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
761 uint64_t Offset =
762 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
763 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
764}
765
767 assert(TU < Hdr.ForeignTypeUnitCount);
768 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
769 uint64_t Offset =
770 Offsets.CUsBase +
771 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
772 return Section.AccelSection.getU64(&Offset);
773}
774
777 const DWARFDataExtractor &AS = Section.AccelSection;
778 if (!AS.isValidOffset(*Offset))
780 "Incorrectly terminated entry list.");
781
782 uint32_t AbbrevCode = AS.getULEB128(Offset);
783 if (AbbrevCode == 0)
785
786 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
787 if (AbbrevIt == Abbrevs.end())
788 return createStringError(errc::invalid_argument, "Invalid abbreviation.");
789
790 Entry E(*this, *AbbrevIt);
791
792 dwarf::FormParams FormParams = {Hdr.Version, 0, Hdr.Format};
793 for (auto &Value : E.Values) {
794 if (!Value.extractValue(AS, Offset, FormParams))
796 "Error extracting index attribute values.");
797 }
798 return std::move(E);
799}
800
803 assert(0 < Index && Index <= Hdr.NameCount);
804 const unsigned SectionOffsetSize = dwarf::getDwarfOffsetByteSize(Hdr.Format);
805 uint64_t StringOffsetOffset =
806 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
807 uint64_t EntryOffsetOffset =
808 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
809 const DWARFDataExtractor &AS = Section.AccelSection;
810
811 uint64_t StringOffset =
812 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
813 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
814 EntryOffset += Offsets.EntriesBase;
815 return {Section.StringSection, Index, StringOffset, EntryOffset};
816}
817
820 assert(Bucket < Hdr.BucketCount);
821 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
822 return Section.AccelSection.getU32(&BucketOffset);
823}
824
826 assert(0 < Index && Index <= Hdr.NameCount);
827 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
828 return Section.AccelSection.getU32(&HashOffset);
829}
830
831// Returns true if we should continue scanning for entries, false if this is the
832// last (sentinel) entry). In case of a parsing error we also return false, as
833// it's not possible to recover this entry list (but the other lists may still
834// parse OK).
835bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
836 uint64_t *Offset) const {
837 uint64_t EntryId = *Offset;
838 auto EntryOr = getEntry(Offset);
839 if (!EntryOr) {
840 handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
841 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
842 return false;
843 }
844
845 DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
846 EntryOr->dump(W);
847 return true;
848}
849
850void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
851 const NameTableEntry &NTE,
852 std::optional<uint32_t> Hash) const {
853 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
854 if (Hash)
855 W.printHex("Hash", *Hash);
856
857 W.startLine() << formatv("String: {0:x8}", NTE.getStringOffset());
858 W.getOStream() << " \"" << NTE.getString() << "\"\n";
859
860 uint64_t EntryOffset = NTE.getEntryOffset();
861 while (dumpEntry(W, &EntryOffset))
862 /*empty*/;
863}
864
865void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
866 ListScope CUScope(W, "Compilation Unit offsets");
867 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
868 W.startLine() << formatv("CU[{0}]: {1:x8}\n", CU, getCUOffset(CU));
869}
870
871void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
872 if (Hdr.LocalTypeUnitCount == 0)
873 return;
874
875 ListScope TUScope(W, "Local Type Unit offsets");
876 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
877 W.startLine() << formatv("LocalTU[{0}]: {1:x8}\n", TU,
878 getLocalTUOffset(TU));
879}
880
881void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
882 if (Hdr.ForeignTypeUnitCount == 0)
883 return;
884
885 ListScope TUScope(W, "Foreign Type Unit signatures");
886 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
887 W.startLine() << formatv("ForeignTU[{0}]: {1:x16}\n", TU,
888 getForeignTUSignature(TU));
889 }
890}
891
892void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
893 ListScope AbbrevsScope(W, "Abbreviations");
894 std::vector<const Abbrev *> AbbrevsVect;
895 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
896 AbbrevsVect.push_back(&Abbr);
897 llvm::sort(AbbrevsVect, [](const Abbrev *LHS, const Abbrev *RHS) {
898 return LHS->AbbrevOffset < RHS->AbbrevOffset;
899 });
900 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
901 Abbr->dump(W);
902}
903
904void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
905 uint32_t Bucket) const {
906 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
907 uint32_t Index = getBucketArrayEntry(Bucket);
908 if (Index == 0) {
909 W.printString("EMPTY");
910 return;
911 }
912 if (Index > Hdr.NameCount) {
913 W.printString("Name index is invalid");
914 return;
915 }
916
917 for (; Index <= Hdr.NameCount; ++Index) {
918 uint32_t Hash = getHashArrayEntry(Index);
919 if (Hash % Hdr.BucketCount != Bucket)
920 break;
921
922 dumpName(W, getNameTableEntry(Index), Hash);
923 }
924}
925
927 DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
928 Hdr.dump(W);
929 dumpCUs(W);
930 dumpLocalTUs(W);
931 dumpForeignTUs(W);
932 dumpAbbreviations(W);
933
934 if (Hdr.BucketCount > 0) {
935 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
936 dumpBucket(W, Bucket);
937 return;
938 }
939
940 W.startLine() << "Hash table not present\n";
941 for (const NameTableEntry &NTE : *this)
942 dumpName(W, NTE, std::nullopt);
943}
944
946 uint64_t Offset = 0;
947 while (AccelSection.isValidOffset(Offset)) {
948 NameIndex Next(*this, Offset);
949 if (Error E = Next.extract())
950 return E;
951 Offset = Next.getNextUnitOffset();
952 NameIndices.push_back(std::move(Next));
953 }
954 return Error::success();
955}
956
961
963 ScopedPrinter W(OS);
964 for (const NameIndex &NI : NameIndices)
965 NI.dump(W);
966}
967
968std::optional<uint64_t>
969DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
970 const Header &Hdr = CurrentIndex->Hdr;
971 if (Hdr.BucketCount == 0) {
972 // No Hash Table, We need to search through all names in the Name Index.
973 for (const NameTableEntry &NTE : *CurrentIndex) {
974 if (NTE.sameNameAs(Key))
975 return NTE.getEntryOffset();
976 }
977 return std::nullopt;
978 }
979
980 // The Name Index has a Hash Table, so use that to speed up the search.
981 // Compute the Key Hash, if it has not been done already.
982 if (!Hash)
983 Hash = caseFoldingDjbHash(Key);
984 uint32_t Bucket = *Hash % Hdr.BucketCount;
985 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
986 if (Index == 0)
987 return std::nullopt; // Empty bucket
988
989 for (; Index <= Hdr.NameCount; ++Index) {
990 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
991 if (HashAtIndex % Hdr.BucketCount != Bucket)
992 return std::nullopt; // End of bucket
993 // Only compare names if the hashes match.
994 if (HashAtIndex != Hash)
995 continue;
996
997 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
998 if (NTE.sameNameAs(Key))
999 return NTE.getEntryOffset();
1000 }
1001 return std::nullopt;
1002}
1003
1004bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
1005 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
1006 if (!EntryOr) {
1007 consumeError(EntryOr.takeError());
1008 return false;
1009 }
1010 CurrentEntry = std::move(*EntryOr);
1011 return true;
1012}
1013
1014bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1015 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1016 if (!Offset)
1017 return false;
1018 DataOffset = *Offset;
1019 return getEntryAtCurrentOffset();
1020}
1021
1022void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1023 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1024 CurrentIndex != End; ++CurrentIndex) {
1025 if (findInCurrentIndex())
1026 return;
1027 }
1028 setEnd();
1029}
1030
1031void DWARFDebugNames::ValueIterator::next() {
1032 assert(CurrentIndex && "Incrementing an end() iterator?");
1033
1034 // First try the next entry in the current Index.
1035 if (getEntryAtCurrentOffset())
1036 return;
1037
1038 // If we're a local iterator or we have reached the last Index, we're done.
1039 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1040 setEnd();
1041 return;
1042 }
1043
1044 // Otherwise, try the next index.
1045 ++CurrentIndex;
1046 searchFromStartOfCurrentIndex();
1047}
1048
1050 StringRef Key)
1051 : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false),
1052 Key(std::string(Key)) {
1053 searchFromStartOfCurrentIndex();
1054}
1055
1058 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1059 if (!findInCurrentIndex())
1060 setEnd();
1061}
1062
1065 if (NameIndices.empty())
1067 return make_range(ValueIterator(*this, Key), ValueIterator());
1068}
1069
1072 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
1073 for (const auto &NI : *this) {
1074 for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
1075 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1076 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
1077 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
1078 }
1079 }
1080 return UnitOffsetToNameIndex.lookup(UnitOffset);
1081}
1082
1083static bool isObjCSelector(StringRef Name) {
1084 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1085 (Name[1] == '[');
1086}
1087
1088std::optional<ObjCSelectorNames> llvm::getObjCNamesIfSelector(StringRef Name) {
1089 if (!isObjCSelector(Name))
1090 return std::nullopt;
1091 // "-[Atom setMass:]"
1092 StringRef ClassNameStart(Name.drop_front(2));
1093 size_t FirstSpace = ClassNameStart.find(' ');
1094 if (FirstSpace == StringRef::npos)
1095 return std::nullopt;
1096
1097 StringRef SelectorStart = ClassNameStart.drop_front(FirstSpace + 1);
1098 if (!SelectorStart.size())
1099 return std::nullopt;
1100
1102 Ans.ClassName = ClassNameStart.take_front(FirstSpace);
1103 Ans.Selector = SelectorStart.drop_back(); // drop ']';
1104
1105 // "-[Class(Category) selector :withArg ...]"
1106 if (Ans.ClassName.back() == ')') {
1107 size_t OpenParens = Ans.ClassName.find('(');
1108 if (OpenParens != StringRef::npos) {
1109 Ans.ClassNameNoCategory = Ans.ClassName.take_front(OpenParens);
1110
1111 Ans.MethodNameNoCategory = Name.take_front(OpenParens + 2);
1112 // FIXME: The missing space here may be a bug, but dsymutil-classic also
1113 // does it this way.
1114 append_range(*Ans.MethodNameNoCategory, SelectorStart);
1115 }
1116 }
1117 return Ans;
1118}
1119
1120std::optional<StringRef> llvm::StripTemplateParameters(StringRef Name) {
1121 // We are looking for template parameters to strip from Name. e.g.
1122 //
1123 // operator<<B>
1124 //
1125 // We look for > at the end but if it does not contain any < then we
1126 // have something like operator>>. We check for the operator<=> case.
1127 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1128 return {};
1129
1130 // How many < until we have the start of the template parameters.
1131 size_t NumLeftAnglesToSkip = 1;
1132
1133 // If we have operator<=> then we need to skip its < as well.
1134 NumLeftAnglesToSkip += Name.count("<=>");
1135
1136 size_t RightAngleCount = Name.count('>');
1137 size_t LeftAngleCount = Name.count('<');
1138
1139 // If we have more < than > we have operator< or operator<<
1140 // we to account for their < as well.
1141 if (LeftAngleCount > RightAngleCount)
1142 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1143
1144 size_t StartOfTemplate = 0;
1145 while (NumLeftAnglesToSkip--)
1146 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1147
1148 StringRef Result = Name.substr(0, StartOfTemplate - 1);
1149 if (Result.empty())
1150 return std::nullopt;
1151 return Result;
1152}
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:1064
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:945
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:967
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1196
@ DW_ATOM_type_flags
Definition Dwarf.h:1035
@ DW_ATOM_die_tag
Definition Dwarf.h:1034
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
Definition Dwarf.h:1031
@ DW_ATOM_cu_offset
Definition Dwarf.h:1032
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:856
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:2224
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:869
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
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:1209