LLVM: lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10
20#include
21#include
22#include
23
24using namespace llvm;
25
26namespace {
27struct Atom {
28 unsigned Value;
29};
30
33 if (!Str.empty())
34 return OS << Str;
35 return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
36}
37}
38
39static Atom formatAtom(unsigned Atom) { return {Atom}; }
40
42
45
46
49 "Section too small: cannot read header.");
50
58
59
60
61 if (.isValidOffset(getIthBucketBase(Hdr.BucketCount - 1)))
64 "Section too small: cannot read buckets and hashes.");
65
68
69 HashDataEntryLength = 0;
70 auto MakeUnsupportedFormError = [](dwarf::Form Form) {
72 "Unsupported form:" +
74 };
75
76 for (unsigned i = 0; i < NumAtoms; ++i) {
79 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
80
81 std::optional<uint8_t> FormSize =
83 if (!FormSize)
84 return MakeUnsupportedFormError(AtomForm);
85 HashDataEntryLength += *FormSize;
86 }
87
88 IsValid = true;
90}
91
93 return Hdr.BucketCount;
94}
98 return Hdr.HeaderDataLength;
99}
100
101ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
102 AppleAcceleratorTable::HeaderData::Form>>
104 return HdrData.Atoms;
105}
106
110 switch (Atom.first) {
116 FormValue.getForm() == dwarf::DW_FORM_sdata)
117 return false;
118 break;
119 default:
120 break;
121 }
122 }
123 return true;
124}
125
126std::pair<uint64_t, dwarf::Tag>
129 dwarf::Tag DieTag = dwarf::DW_TAG_null;
130
134 switch (Atom.first) {
137 break;
140 break;
141 default:
142 break;
143 }
144 }
145 return {DieOffset, DieTag};
146}
147
148void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
149 DictScope HeaderScope(W, "Header");
150 W.printHex("Magic", Magic);
151 W.printHex("Version", Version);
152 W.printHex("Hash function", HashFunction);
153 W.printNumber("Bucket count", BucketCount);
154 W.printNumber("Hashes count", HashCount);
155 W.printNumber("HeaderData length", HeaderDataLength);
156}
157
158std::optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
159 std::optional Value) const {
161 return std::nullopt;
162
163 switch (Value->getForm()) {
164 case dwarf::DW_FORM_ref1:
165 case dwarf::DW_FORM_ref2:
166 case dwarf::DW_FORM_ref4:
167 case dwarf::DW_FORM_ref8:
168 case dwarf::DW_FORM_ref_udata:
169 return Value->getRawUValue() + DIEOffsetBase;
170 default:
171 return Value->getAsSectionOffset();
172 }
173}
174
175bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
176 SmallVectorImpl &AtomForms,
177 uint64_t *DataOffset) const {
178 uint64_t NameOffset = *DataOffset;
179 if (.isValidOffsetForDataOfSize(*DataOffset, 4)) {
180 W.printString("Incorrectly terminated list.");
181 return false;
182 }
183 uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
184 if (!StringOffset)
185 return false;
186
187 DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
188 W.startLine() << format("String: 0x%08" PRIx64, StringOffset);
189 W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";
190
191 unsigned NumData = AccelSection.getU32(DataOffset);
192 for (unsigned Data = 0; Data < NumData; ++Data) {
193 ListScope DataScope(W, ("Data " + Twine(Data)).str());
194 unsigned i = 0;
195 for (auto &Atom : AtomForms) {
196 W.startLine() << format("Atom[%d]: ", i);
197 if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
198 Atom.dump(W.getOStream());
199 if (std::optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
201 if (!Str.empty())
202 W.getOStream() << " (" << Str << ")";
203 }
204 } else
205 W.getOStream() << "Error extracting the value";
206 W.getOStream() << "\n";
207 i++;
208 }
209 }
210 return true;
211}
212
214 if (!IsValid)
215 return;
216
218
219 Hdr.dump(W);
220
221 W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
222 W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
225 {
226 ListScope AtomsScope(W, "Atoms");
227 unsigned i = 0;
228 for (const auto &Atom : HdrData.Atoms) {
229 DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
230 W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
231 W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
233 }
234 }
235
236
237 uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
239 uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;
240
241 for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
243
244 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
245 if (Index == UINT32_MAX) {
246 W.printString("EMPTY");
247 continue;
248 }
249
250 for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
251 uint64_t HashOffset = HashesBase + HashIdx*4;
252 uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
254
255 if (Hash % Hdr.BucketCount != Bucket)
256 break;
257
260 if (.isValidOffset(DataOffset)) {
261 W.printString("Invalid section offset");
262 continue;
263 }
264 while (dumpName(W, AtomForms, &DataOffset))
265 ;
266 }
267 }
268}
269
271 : Table(Table) {
272 Values.reserve(Table.HdrData.Atoms.size());
273 for (const auto &Atom : Table.HdrData.Atoms)
275}
276
277void AppleAcceleratorTable::Entry::extract(uint64_t *Offset) {
278 for (auto &FormValue : Values)
279 FormValue.extractValue(Table.AccelSection, Offset, Table.FormParams);
280}
281
282std::optional
284 for (auto [Atom, FormValue] : zip_equal(Table.HdrData.Atoms, Values))
285 if (Atom.first == AtomToFind)
286 return FormValue;
287 return std::nullopt;
288}
289
290std::optional<uint64_t>
294
298
301 if ()
302 return std::nullopt;
303 if (std::optional<uint64_t> Value = Tag->getAsUnsignedConstant())
305 return std::nullopt;
306}
307
311
312void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() {
313 if (NumEntriesToCome == 0)
314 prepareNextStringOrEnd();
315 if (isEnd())
316 return;
318 Current.BaseEntry.extract(&OffsetCopy);
319 NumEntriesToCome--;
320 Offset += getTable().getHashDataEntryLength();
321}
322
323void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() {
326
327
328 std::optional<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);
329 if (!OptOffset)
330 return setToEnd();
332 }
333 std::optional<uint32_t> StrOffset = Table.readStringOffsetAt(Offset);
334 if (!StrOffset)
335 return setToEnd();
336
337
338
339
340 if (*StrOffset == 0) {
342 return prepareNextStringOrEnd();
343 }
344 Current.StrOffset = *StrOffset;
345
346 std::optional<uint32_t> MaybeNumEntries = Table.readU32FromAccel(Offset);
347 if (!MaybeNumEntries || *MaybeNumEntries == 0)
348 return setToEnd();
349 NumEntriesToCome = *MaybeNumEntries;
350}
351
353 bool SetEnd)
354 : Current(Table), Offset(0), NumEntriesToCome(0) {
355 if (SetEnd)
356 setToEnd();
357 else
358 prepareNextEntryOrEnd();
359}
360
363 const auto EmptyRange =
365 if (!IsValid)
366 return EmptyRange;
367
368
370 uint32_t BucketIdx = hashToBucketIdx(SearchHash);
371 std::optional<uint32_t> HashIdx = idxOfHashInBucket(SearchHash, BucketIdx);
372 if (!HashIdx)
373 return EmptyRange;
374
375 std::optional<uint64_t> MaybeDataOffset = readIthOffset(*HashIdx);
376 if (!MaybeDataOffset)
377 return EmptyRange;
378
379 uint64_t DataOffset = *MaybeDataOffset;
381 return EmptyRange;
382
383 std::optional<uint32_t> StrOffset = readStringOffsetAt(DataOffset);
384
385 while (StrOffset && *StrOffset) {
386 std::optional MaybeStr = readStringFromStrSection(*StrOffset);
387 std::optional<uint32_t> NumEntries = this->readU32FromAccel(DataOffset);
388 if (!MaybeStr || !NumEntries)
389 return EmptyRange;
391 if (Key == *MaybeStr)
392 return make_range({*this, DataOffset},
394 DataOffset = EndOffset;
395 StrOffset = readStringOffsetAt(DataOffset);
396 }
397
398 return EmptyRange;
399}
400
401std::optional<uint32_t>
402AppleAcceleratorTable::idxOfHashInBucket(uint32_t HashToFind,
404 std::optional<uint32_t> HashStartIdx = readIthBucket(BucketIdx);
405 if (!HashStartIdx)
406 return std::nullopt;
407
408 for (uint32_t HashIdx = *HashStartIdx; HashIdx < getNumHashes(); HashIdx++) {
409 std::optional<uint32_t> MaybeHash = readIthHash(HashIdx);
410 if (!MaybeHash || !wouldHashBeInBucket(*MaybeHash, BucketIdx))
411 break;
412 if (*MaybeHash == HashToFind)
413 return HashIdx;
414 }
415 return std::nullopt;
416}
417
418std::optional AppleAcceleratorTable::readStringFromStrSection(
419 uint64_t StringSectionOffset) const {
421 StringRef Str = StringSection.getCStrRef(&StringSectionOffset, &E);
422 if (E) {
424 return std::nullopt;
425 }
426 return Str;
427}
428
429std::optional<uint32_t>
430AppleAcceleratorTable::readU32FromAccel(uint64_t &Offset,
431 bool UseRelocation) const {
433 uint32_t Data = UseRelocation
436 if (E) {
438 return std::nullopt;
439 }
441}
442
456
461 "parsing .debug_names header at 0x%" PRIx64 ": %s",
463 };
464
467
477
478 if ()
479 return HeaderError(C.takeError());
480
483 "cannot read header augmentation"));
488 return C.takeError();
489}
490
493 W.startLine() << formatv("Tag: {0}\n", Tag);
494
496 W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
497}
498
502
506
510
512 return Abbr.Code == 0;
513}
514
515DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
517}
518
519DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
520 return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), 0, {});
521}
522
523ExpectedDWARFDebugNames::AttributeEncoding
524DWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
527 "Incorrectly terminated abbreviation table.");
528 }
529
533}
534
535Expected<std::vectorDWARFDebugNames::AttributeEncoding>
536DWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
537 std::vector Result;
538 for (;;) {
539 auto AttrEncOr = extractAttributeEncoding(Offset);
540 if (!AttrEncOr)
541 return AttrEncOr.takeError();
543 return std::move(Result);
544
545 Result.emplace_back(*AttrEncOr);
546 }
547}
548
549ExpectedDWARFDebugNames::Abbrev
550DWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
553 "Incorrectly terminated abbreviation table.");
554 }
555 const uint64_t AbbrevOffset = *Offset;
557 if (Code == 0)
559
561 auto AttrEncOr = extractAttributeEncodings(Offset);
562 if (!AttrEncOr)
563 return AttrEncOr.takeError();
564 return Abbrev(Code, dwarf::Tag(Tag), AbbrevOffset, std::move(*AttrEncOr));
565}
566
567DWARFDebugNames::DWARFDebugNamesOffsets
572 Ret.CUsBase = EndOfHeaderOffset;
582 return Ret;
583}
584
587 uint64_t EndOfHeaderOffset = Base;
588 if (Error E = Hdr.extract(AS, &EndOfHeaderOffset))
589 return E;
590
593
595 Offsets.EntryOffsetsBase + (Hdr.NameCount * SectionOffsetSize);
596
599 "Section too small: cannot read abbreviations.");
600
601 Offsets.EntriesBase = Offset + Hdr.AbbrevTableSize;
602
603 for (;;) {
604 auto AbbrevOr = extractAbbrev(&Offset);
605 if (!AbbrevOr)
606 return AbbrevOr.takeError();
609
610 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
612 "Duplicate abbreviation code.");
613 }
614}
615
617 : NameIdx(&NameIdx), Abbr(&Abbr) {
618
619
620 Values.reserve(Abbr.Attributes.size());
622 Values.emplace_back(Attr.Form);
623}
624
625std::optional
627 assert(Abbr->Attributes.size() == Values.size());
629 if (std::get<0>(Tuple).Index == Index)
630 return std::get<1>(Tuple);
631 }
632 return std::nullopt;
633}
634
636 return lookup(dwarf::DW_IDX_parent).has_value();
637}
638
640 if (std::optional Off = lookup(dwarf::DW_IDX_die_offset))
641 return Off->getAsReferenceUVal();
642 return std::nullopt;
643}
644
646
647 if (std::optional Off = lookup(dwarf::DW_IDX_compile_unit))
648 return Off->getAsUnsignedConstant();
649
650
651 if (NameIdx->getCUCount() == 1)
652 return 0;
653 return std::nullopt;
654}
655
657
658
659
660 if (lookup(dwarf::DW_IDX_type_unit).has_value())
661 return std::nullopt;
663}
664
666 std::optional<uint64_t> Index = getCUIndex();
667 if (!Index || *Index >= NameIdx->getCUCount())
668 return std::nullopt;
669 return NameIdx->getCUOffset(*Index);
670}
671
674 if (!Index || *Index >= NameIdx->getCUCount())
675 return std::nullopt;
676 return NameIdx->getCUOffset(*Index);
677}
678
680 std::optional<uint64_t> Index = getTUIndex();
681 if (!Index || *Index >= NameIdx->getLocalTUCount())
682 return std::nullopt;
683 return NameIdx->getLocalTUOffset(*Index);
684}
685
686std::optional<uint64_t>
688 std::optional<uint64_t> Index = getTUIndex();
689 const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
690 if (!Index || *Index < NumLocalTUs)
691 return std::nullopt;
692
693 const uint64_t ForeignTUIndex = *Index - NumLocalTUs;
694 if (ForeignTUIndex >= NameIdx->getForeignTUCount())
695 return std::nullopt;
696 return NameIdx->getForeignTUSignature(ForeignTUIndex);
697}
698
700 if (std::optional Off = lookup(dwarf::DW_IDX_type_unit))
701 return Off->getAsUnsignedConstant();
702 return std::nullopt;
703}
704
707
708 std::optional ParentEntryOff = lookup(dwarf::DW_IDX_parent);
709 assert(ParentEntryOff.has_value() && "hasParentInformation() must be called");
710
711 if (ParentEntryOff->getForm() == dwarf::Form::DW_FORM_flag_present)
712 return std::nullopt;
713 return NameIdx->getEntryAtRelativeOffset(ParentEntryOff->getRawUValue());
714}
715
719 if (!ParentEntry) {
720 W.getOStream() << "";
722 return;
723 }
724
725 if (!ParentEntry->has_value()) {
726 W.getOStream() << "";
727 return;
728 }
729
730 auto AbsoluteOffset = NameIdx->Offsets.EntriesBase + FormValue.getRawUValue();
731 W.getOStream() << "Entry @ 0x" + Twine::utohexstr(AbsoluteOffset);
732}
733
735 W.startLine() << formatv("Abbrev: {0:x}\n", Abbr->Code);
736 W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
737 assert(Abbr->Attributes.size() == Values.size());
739 auto Index = std::get<0>(Tuple).Index;
740 W.startLine() << formatv("{0}: ", Index);
741
742 auto FormValue = std::get<1>(Tuple);
743 if (Index == dwarf::Index::DW_IDX_parent)
745 else
746 FormValue.dump(W.getOStream());
747 W.getOStream() << '\n';
748 }
749}
750
755
757 assert(CU < Hdr.CompUnitCount);
760 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
761}
762
764 assert(TU < Hdr.LocalTypeUnitCount);
767 Offsets.CUsBase + SectionOffsetSize * (Hdr.CompUnitCount + TU);
768 return Section.AccelSection.getRelocatedValue(SectionOffsetSize, &Offset);
769}
770
772 assert(TU < Hdr.ForeignTypeUnitCount);
775 Offsets.CUsBase +
776 SectionOffsetSize * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
777 return Section.AccelSection.getU64(&Offset);
778}
779
785 "Incorrectly terminated entry list.");
786
788 if (AbbrevCode == 0)
790
791 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
792 if (AbbrevIt == Abbrevs.end())
794
795 Entry E(*this, *AbbrevIt);
796
798 for (auto &Value : E.Values) {
799 if (.extractValue(AS, Offset, FormParams))
801 "Error extracting index attribute values.");
802 }
803 return std::move(E);
804}
805
808 assert(0 < Index && Index <= Hdr.NameCount);
810 uint64_t StringOffsetOffset =
811 Offsets.StringOffsetsBase + SectionOffsetSize * (Index - 1);
813 Offsets.EntryOffsetsBase + SectionOffsetSize * (Index - 1);
815
817 AS.getRelocatedValue(SectionOffsetSize, &StringOffsetOffset);
818 uint64_t EntryOffset = AS.getUnsigned(&EntryOffsetOffset, SectionOffsetSize);
819 EntryOffset += Offsets.EntriesBase;
820 return {Section.StringSection, Index, StringOffset, EntryOffset};
821}
822
825 assert(Bucket < Hdr.BucketCount);
826 uint64_t BucketOffset = Offsets.BucketsBase + 4 * Bucket;
827 return Section.AccelSection.getU32(&BucketOffset);
828}
829
831 assert(0 < Index && Index <= Hdr.NameCount);
832 uint64_t HashOffset = Offsets.HashesBase + 4 * (Index - 1);
833 return Section.AccelSection.getU32(&HashOffset);
834}
835
836
837
838
839
840bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
843 auto EntryOr = getEntry(Offset);
844 if (!EntryOr) {
846 [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
847 return false;
848 }
849
851 EntryOr->dump(W);
852 return true;
853}
854
855void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
856 const NameTableEntry &NTE,
857 std::optional<uint32_t> Hash) const {
858 DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
859 if (Hash)
860 W.printHex("Hash", *Hash);
861
862 W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());
863 W.getOStream() << " \"" << NTE.getString() << "\"\n";
864
865 uint64_t EntryOffset = NTE.getEntryOffset();
866 while (dumpEntry(W, &EntryOffset))
867 ;
868}
869
870void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
871 ListScope CUScope(W, "Compilation Unit offsets");
872 for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
873 W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));
874}
875
876void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
877 if (Hdr.LocalTypeUnitCount == 0)
878 return;
879
880 ListScope TUScope(W, "Local Type Unit offsets");
881 for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
882 W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,
883 getLocalTUOffset(TU));
884}
885
886void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
887 if (Hdr.ForeignTypeUnitCount == 0)
888 return;
889
890 ListScope TUScope(W, "Foreign Type Unit signatures");
891 for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
892 W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
893 getForeignTUSignature(TU));
894 }
895}
896
897void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
898 ListScope AbbrevsScope(W, "Abbreviations");
899 std::vector<const Abbrev *> AbbrevsVect;
900 for (const DWARFDebugNames::Abbrev &Abbr : Abbrevs)
901 AbbrevsVect.push_back(&Abbr);
903 return LHS->AbbrevOffset < RHS->AbbrevOffset;
904 });
905 for (const DWARFDebugNames::Abbrev *Abbr : AbbrevsVect)
906 Abbr->dump(W);
907}
908
909void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
910 uint32_t Bucket) const {
911 ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
912 uint32_t Index = getBucketArrayEntry(Bucket);
913 if (Index == 0) {
914 W.printString("EMPTY");
915 return;
916 }
917 if (Index > Hdr.NameCount) {
918 W.printString("Name index is invalid");
919 return;
920 }
921
922 for (; Index <= Hdr.NameCount; ++Index) {
923 uint32_t Hash = getHashArrayEntry(Index);
924 if (Hash % Hdr.BucketCount != Bucket)
925 break;
926
927 dumpName(W, getNameTableEntry(Index), Hash);
928 }
929}
930
933 Hdr.dump(W);
934 dumpCUs(W);
935 dumpLocalTUs(W);
936 dumpForeignTUs(W);
937 dumpAbbreviations(W);
938
939 if (Hdr.BucketCount > 0) {
940 for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
941 dumpBucket(W, Bucket);
942 return;
943 }
944
945 W.startLine() << "Hash table not present\n";
947 dumpName(W, NTE, std::nullopt);
948}
949
955 return E;
957 NameIndices.push_back(std::move(Next));
958 }
960}
961
966
969 for (const NameIndex &NI : NameIndices)
970 NI.dump(W);
971}
972
973std::optional<uint64_t>
974DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
975 const Header &Hdr = CurrentIndex->Hdr;
976 if (Hdr.BucketCount == 0) {
977
978 for (const NameTableEntry &NTE : *CurrentIndex) {
979 if (NTE.sameNameAs(Key))
980 return NTE.getEntryOffset();
981 }
982 return std::nullopt;
983 }
984
985
986
987 if (!Hash)
989 uint32_t Bucket = *Hash % Hdr.BucketCount;
990 uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
991 if (Index == 0)
992 return std::nullopt;
993
994 for (; Index <= Hdr.NameCount; ++Index) {
995 uint32_t HashAtIndex = CurrentIndex->getHashArrayEntry(Index);
996 if (HashAtIndex % Hdr.BucketCount != Bucket)
997 return std::nullopt;
998
999 if (HashAtIndex != Hash)
1000 continue;
1001
1002 NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
1003 if (NTE.sameNameAs(Key))
1005 }
1006 return std::nullopt;
1007}
1008
1009bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
1010 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
1011 if (!EntryOr) {
1013 return false;
1014 }
1015 CurrentEntry = std::move(*EntryOr);
1016 return true;
1017}
1018
1019bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
1020 std::optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
1022 return false;
1023 DataOffset = *Offset;
1024 return getEntryAtCurrentOffset();
1025}
1026
1027void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
1028 for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
1029 CurrentIndex != End; ++CurrentIndex) {
1030 if (findInCurrentIndex())
1031 return;
1032 }
1033 setEnd();
1034}
1035
1036void DWARFDebugNames::ValueIterator::next() {
1037 assert(CurrentIndex && "Incrementing an end() iterator?");
1038
1039
1040 if (getEntryAtCurrentOffset())
1041 return;
1042
1043
1044 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
1045 setEnd();
1046 return;
1047 }
1048
1049
1050 ++CurrentIndex;
1051 searchFromStartOfCurrentIndex();
1052}
1053
1057 Key(std::string(Key)) {
1058 searchFromStartOfCurrentIndex();
1059}
1060
1063 : CurrentIndex(&NI), IsLocal(true), Key(std::string(Key)) {
1064 if (!findInCurrentIndex())
1065 setEnd();
1066}
1067
1070 if (NameIndices.empty())
1073}
1074
1077 if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
1078 for (const auto &NI : *this) {
1080 UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
1081 for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
1082 UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
1083 }
1084 }
1085 return UnitOffsetToNameIndex.lookup(UnitOffset);
1086}
1087
1089 return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
1090 (Name[1] == '[');
1091}
1092
1095 return std::nullopt;
1096
1097 StringRef ClassNameStart(Name.drop_front(2));
1098 size_t FirstSpace = ClassNameStart.find(' ');
1100 return std::nullopt;
1101
1103 if (!SelectorStart.size())
1104 return std::nullopt;
1105
1109
1110
1115
1117
1118
1120 }
1121 }
1122 return Ans;
1123}
1124
1126
1127
1128
1129
1130
1131
1132 if (!Name.ends_with(">") || Name.count("<") == 0 || Name.ends_with("<=>"))
1133 return {};
1134
1135
1136 size_t NumLeftAnglesToSkip = 1;
1137
1138
1139 NumLeftAnglesToSkip += Name.count("<=>");
1140
1141 size_t RightAngleCount = Name.count('>');
1142 size_t LeftAngleCount = Name.count('<');
1143
1144
1145
1146 if (LeftAngleCount > RightAngleCount)
1147 NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount;
1148
1149 size_t StartOfTemplate = 0;
1150 while (NumLeftAnglesToSkip--)
1151 StartOfTemplate = Name.find('<', StartOfTemplate) + 1;
1152
1153 return Name.substr(0, StartOfTemplate - 1);
1154}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc()
Definition DWARFAcceleratorTable.cpp:499
static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE)
Definition DWARFAcceleratorTable.cpp:503
static DWARFDebugNames::Abbrev sentinelAbbrev()
Definition DWARFAcceleratorTable.cpp:507
static bool isObjCSelector(StringRef Name)
Definition DWARFAcceleratorTable.cpp:1088
static Atom formatAtom(unsigned Atom)
Definition DWARFAcceleratorTable.cpp:39
This file contains constants used for implementing Dwarf debug support.
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
#define offsetof(TYPE, MEMBER)
This file defines the SmallVector class.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
std::optional< DWARFFormValue > lookup(HeaderData::AtomType Atom) const
Returns the value of the Atom in this Accelerator Entry, if the Entry contains such Atom.
Definition DWARFAcceleratorTable.cpp:283
std::optional< uint64_t > getDIESectionOffset() const
Returns the Section Offset of the Debug Info Entry associated with this Accelerator Entry or std::nul...
Definition DWARFAcceleratorTable.cpp:291
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...
Definition DWARFAcceleratorTable.cpp:299
std::optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...
Definition DWARFAcceleratorTable.cpp:295
LLVM_ABI Iterator(const AppleAcceleratorTable &Table, bool SetEnd=false)
Definition DWARFAcceleratorTable.cpp:352
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.
Definition DWARFAcceleratorTable.cpp:308
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
Error extract() override
Definition DWARFAcceleratorTable.cpp:43
iterator_range< SameNameIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
Definition DWARFAcceleratorTable.cpp:362
AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)
uint32_t getNumBuckets() const
Definition DWARFAcceleratorTable.cpp:92
bool validateForms()
Definition DWARFAcceleratorTable.cpp:107
uint32_t getSizeHdr() const
Definition DWARFAcceleratorTable.cpp:96
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.
Definition DWARFAcceleratorTable.cpp:127
uint32_t getNumHashes() const
Definition DWARFAcceleratorTable.cpp:95
uint32_t getHashDataEntryLength() const
Returns the size of one HashData entry.
void dump(raw_ostream &OS) const override
Definition DWARFAcceleratorTable.cpp:213
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...
Definition DWARFAcceleratorTable.cpp:103
uint32_t getHeaderDataLength() const
Definition DWARFAcceleratorTable.cpp:97
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
SmallVector< DWARFFormValue, 3 > Values
DataExtractor StringSection
virtual ~DWARFAcceleratorTable()
DWARFDataExtractor AccelSection
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...
Definition DWARFAcceleratorTable.cpp:687
std::optional< uint64_t > getRelatedCUIndex() const
Similar functionality to getCUIndex() but without the DW_IDX_type_unit restriction.
Definition DWARFAcceleratorTable.cpp:645
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...
Definition DWARFAcceleratorTable.cpp:656
std::optional< uint64_t > getRelatedCUOffset() const
Definition DWARFAcceleratorTable.cpp:672
std::optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or std::nullopt if ...
Definition DWARFAcceleratorTable.cpp:665
std::optional< uint64_t > getDIEUnitOffset() const
Returns the Offset of the DIE within the containing CU or TU.
Definition DWARFAcceleratorTable.cpp:639
Expected< std::optional< DWARFDebugNames::Entry > > getParentDIEEntry() const
Returns the Entry corresponding to the parent of the DIE represented by this Entry.
Definition DWARFAcceleratorTable.cpp:706
bool hasParentInformation() const
Returns true if this Entry has information about its parent DIE (i.e.
Definition DWARFAcceleratorTable.cpp:635
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...
Definition DWARFAcceleratorTable.cpp:699
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...
Definition DWARFAcceleratorTable.cpp:626
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...
Definition DWARFAcceleratorTable.cpp:679
void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const
Definition DWARFAcceleratorTable.cpp:716
void dump(ScopedPrinter &W) const
Definition DWARFAcceleratorTable.cpp:734
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.
Definition DWARFAcceleratorTable.cpp:830
LLVM_ABI uint64_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
Definition DWARFAcceleratorTable.cpp:763
LLVM_ABI uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
Definition DWARFAcceleratorTable.cpp:824
LLVM_ABI void dump(ScopedPrinter &W) const
Definition DWARFAcceleratorTable.cpp:931
LLVM_ABI iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
Definition DWARFAcceleratorTable.cpp:963
LLVM_ABI uint64_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
Definition DWARFAcceleratorTable.cpp:756
LLVM_ABI Expected< Entry > getEntry(uint64_t *Offset) const
Definition DWARFAcceleratorTable.cpp:781
LLVM_ABI NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
Definition DWARFAcceleratorTable.cpp:807
LLVM_ABI Error extract()
Definition DWARFAcceleratorTable.cpp:585
LLVM_ABI uint64_t getForeignTUSignature(uint32_t TU) const
Reads signature of foreign type unit TU. TU is 0-based.
Definition DWARFAcceleratorTable.cpp:771
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.
Definition DWARFAcceleratorTable.cpp:752
ValueIterator()=default
End marker.
const_iterator begin() const
DWARFDebugNames(const DWARFDataExtractor &AccelSection, DataExtractor StringSection)
Error extract() override
Definition DWARFAcceleratorTable.cpp:950
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
Definition DWARFAcceleratorTable.cpp:1069
const NameIndex * getCUOrTUNameIndex(uint64_t UnitOffset)
Return the Name Index covering the compile unit or local type unit at UnitOffset, or nullptr if there...
Definition DWARFAcceleratorTable.cpp:1076
void dump(raw_ostream &OS) const override
Definition DWARFAcceleratorTable.cpp:967
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
Base class for error info classes.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
char back() const
back - Get the last character in the string.
constexpr size_t size() const
size - Get the string size.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(uint64_t Val)
LLVM Value Representation.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
LLVM_ABI StringRef AtomTypeString(unsigned Atom)
LLVM_ABI StringRef FormatString(DwarfFormat Format)
@ C
The default llvm calling convention, compatible with C.
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.
LLVM_ABI DWARFDebugNames::DWARFDebugNamesOffsets findDebugNamesOffsets(uint64_t EndOfHeaderOffset, const DWARFDebugNames::Header &Hdr)
Definition DWARFAcceleratorTable.cpp:568
const uint32_t DW_INVALID_OFFSET
Identifier of an invalid DIE offset in the .debug_info section.
LLVM_ABI std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)
Get the fixed byte size for a given form.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
@ DW_ATOM_die_offset
Marker as the end of a list of atoms.
NodeAddr< CodeNode * > Code
This is an optimization pass for GlobalISel generic memory operations.
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.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
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.
void sort(IteratorTy Start, IteratorTy End)
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...
Definition DWARFAcceleratorTable.cpp:1125
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
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.
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...
Definition DWARFAcceleratorTable.cpp:1093
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
Abbreviation describing the encoding of Name Index entries.
LLVM_ABI void dump(ScopedPrinter &W) const
Definition DWARFAcceleratorTable.cpp:491
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.
Index attribute and its encoding.
Offsets for the start of various important tables from the start of the section.
uint64_t EntryOffsetsBase
uint64_t StringOffsetsBase
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...