37 return OS <<
"DW_ATOM_unknown_" <<
format(
"%x", A.Value);
49 if (!AccelSection.isValidOffset(
offsetof(Header, HeaderDataLength) + 4))
51 "Section too small: cannot read header.");
53 Hdr.Magic = AccelSection.getU32(&Offset);
54 Hdr.Version = AccelSection.getU16(&Offset);
55 Hdr.HashFunction = AccelSection.getU16(&Offset);
56 Hdr.BucketCount = AccelSection.getU32(&Offset);
57 Hdr.HashCount = AccelSection.getU32(&Offset);
58 Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
64 if (!AccelSection.isValidOffset(
sizeof(Hdr) + Hdr.HeaderDataLength +
65 Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1))
68 "Section too small: cannot read buckets and hashes.");
70 HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
71 uint32_t NumAtoms = AccelSection.getU32(&Offset);
73 for (
unsigned i = 0; i < NumAtoms; ++i) {
74 uint16_t AtomType = AccelSection.getU16(&Offset);
75 auto AtomForm =
static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
76 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
87 return Hdr.HeaderDataLength;
90 ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
97 for (
auto Atom : getAtomsDesc()) {
105 FormValue.
getForm() == dwarf::DW_FORM_sdata)
115 std::pair<uint32_t, dwarf::Tag>
121 for (
auto Atom : getAtomsDesc()) {
123 FormValue.
extractValue(AccelSection, &HashDataOffset, FormParams);
124 switch (Atom.first) {
135 return {DieOffset, DieTag};
142 W.
printHex(
"Hash function", HashFunction);
145 W.
printNumber(
"HeaderData length", HeaderDataLength);
154 case dwarf::DW_FORM_ref1:
155 case dwarf::DW_FORM_ref2:
156 case dwarf::DW_FORM_ref4:
157 case dwarf::DW_FORM_ref8:
158 case dwarf::DW_FORM_ref_udata:
170 if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
174 unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
180 W.
getOStream() <<
" \"" << StringSection.getCStr(&StringOffset) <<
"\"\n";
182 unsigned NumData = AccelSection.getU32(DataOffset);
186 for (
auto &Atom : AtomForms) {
188 if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
196 W.
getOStream() <<
"Error extracting the value";
212 W.
printNumber(
"DIE offset base", HdrData.DIEOffsetBase);
213 W.
printNumber(
"Number of atoms", uint64_t(HdrData.Atoms.size()));
218 for (
const auto &Atom : HdrData.Atoms) {
228 unsigned HashesBase = Offset + Hdr.BucketCount * 4;
229 unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;
231 for (
unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
232 unsigned Index = AccelSection.getU32(&Offset);
235 if (Index == UINT32_MAX) {
240 for (
unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
241 unsigned HashOffset = HashesBase + HashIdx*4;
242 unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
243 uint32_t Hash = AccelSection.getU32(&HashOffset);
245 if (Hash % Hdr.BucketCount != Bucket)
248 unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
250 if (!AccelSection.isValidOffset(DataOffset)) {
254 while (dumpName(W, AtomForms, &DataOffset))
260 AppleAcceleratorTable::Entry::Entry(
261 const AppleAcceleratorTable::HeaderData &HdrData)
262 : HdrData(&HdrData) {
263 Values.reserve(HdrData.Atoms.size());
264 for (
const auto &Atom : HdrData.Atoms)
268 void AppleAcceleratorTable::Entry::extract(
273 for (
auto &Atom : Values)
274 Atom.extractValue(AccelTable.
AccelSection, Offset, FormParams);
279 assert(HdrData &&
"Dereferencing end iterator?");
280 assert(HdrData->Atoms.size() == Values.size());
281 for (
const auto &Tuple :
zip_first(HdrData->Atoms, Values)) {
282 if (std::get<0>(Tuple).first == Atom)
283 return std::get<1>(Tuple);
307 : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) {
316 void AppleAcceleratorTable::ValueIterator::Next() {
317 assert(NumData > 0 &&
"attempted to increment iterator past the end");
319 if (Data >= NumData ||
325 Current.extract(*AccelTable, &DataOffset);
335 unsigned HashValue =
djbHash(Key);
336 unsigned Bucket = HashValue % Hdr.BucketCount;
337 unsigned BucketBase =
sizeof(Hdr) + Hdr.HeaderDataLength;
338 unsigned HashesBase = BucketBase + Hdr.BucketCount * 4;
339 unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;
341 unsigned BucketOffset = BucketBase + Bucket * 4;
345 for (
unsigned HashIdx =
Index; HashIdx < Hdr.HashCount; ++HashIdx) {
346 unsigned HashOffset = HashesBase + HashIdx * 4;
347 unsigned OffsetsOffset = OffsetsBase + HashIdx * 4;
350 if (Hash % Hdr.BucketCount != Bucket)
372 W.
printNumber(
"Local TU count", LocalTypeUnitCount);
373 W.
printNumber(
"Foreign TU count", ForeignTypeUnitCount);
376 W.
printHex(
"Abbreviations table size", AbbrevTableSize);
377 W.
startLine() <<
"Augmentation: '" << AugmentationString <<
"'\n";
385 "Section too small: cannot read header.");
387 UnitLength = AS.
getU32(Offset);
389 Padding = AS.
getU16(Offset);
390 CompUnitCount = AS.
getU32(Offset);
391 LocalTypeUnitCount = AS.
getU32(Offset);
392 ForeignTypeUnitCount = AS.
getU32(Offset);
393 BucketCount = AS.
getU32(Offset);
394 NameCount = AS.
getU32(Offset);
395 AbbrevTableSize = AS.
getU32(Offset);
401 "Section too small: cannot read header augmentation.");
402 AugmentationString.resize(AugmentationStringSize);
403 AS.
getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()),
404 AugmentationStringSize);
412 for (
const auto &Attr : Attributes)
429 return Abbr.
Code == 0;
441 DWARFDebugNames::NameIndex::extractAttributeEncoding(
uint32_t *Offset) {
442 if (*Offset >= EntriesBase) {
444 "Incorrectly terminated abbreviation table.");
453 DWARFDebugNames::NameIndex::extractAttributeEncodings(
uint32_t *Offset) {
454 std::vector<AttributeEncoding> Result;
456 auto AttrEncOr = extractAttributeEncoding(Offset);
458 return AttrEncOr.takeError();
460 return std::move(Result);
462 Result.emplace_back(*AttrEncOr);
467 DWARFDebugNames::NameIndex::extractAbbrev(
uint32_t *Offset) {
468 if (*Offset >= EntriesBase) {
470 "Incorrectly terminated abbreviation table.");
478 auto AttrEncOr = extractAttributeEncodings(Offset);
480 return AttrEncOr.takeError();
481 return Abbrev(Code,
dwarf::Tag(Tag), std::move(*AttrEncOr));
487 if (
Error E = Hdr.extract(AS, &Offset))
491 Offset += Hdr.CompUnitCount * 4;
492 Offset += Hdr.LocalTypeUnitCount * 4;
493 Offset += Hdr.ForeignTypeUnitCount * 8;
495 Offset += Hdr.BucketCount * 4;
497 if (Hdr.BucketCount > 0)
498 Offset += Hdr.NameCount * 4;
499 StringOffsetsBase =
Offset;
500 Offset += Hdr.NameCount * 4;
501 EntryOffsetsBase =
Offset;
502 Offset += Hdr.NameCount * 4;
506 "Section too small: cannot read abbreviations.");
508 EntriesBase = Offset + Hdr.AbbrevTableSize;
511 auto AbbrevOr = extractAbbrev(&Offset);
513 return AbbrevOr.takeError();
517 if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
519 "Duplicate abbreviation code.");
523 : NameIdx(&NameIdx), Abbr(&Abbr) {
528 Values.emplace_back(Attr.Form);
535 if (std::get<0>(Tuple).Index ==
Index)
536 return std::get<1>(Tuple);
543 return Off->getAsReferenceUVal();
549 return Off->getAsUnsignedConstant();
559 if (!Index || *Index >= NameIdx->
getCUCount())
581 assert(CU < Hdr.CompUnitCount);
583 return Section.AccelSection.getRelocatedValue(4, &Offset);
587 assert(TU < Hdr.LocalTypeUnitCount);
588 uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4;
589 return Section.AccelSection.getRelocatedValue(4, &Offset);
593 assert(TU < Hdr.ForeignTypeUnitCount);
594 uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4;
595 return Section.AccelSection.getU64(&Offset);
603 "Incorrectly terminated entry list.");
607 return make_error<SentinelError>();
609 const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
610 if (AbbrevIt == Abbrevs.end())
613 Entry E(*
this, *AbbrevIt);
616 for (
auto &Value : E.
Values) {
617 if (!Value.extractValue(AS, Offset, FormParams))
619 "Error extracting index attribute values.");
626 assert(0 < Index && Index <= Hdr.NameCount);
627 uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
628 uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
631 uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
632 uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset);
633 EntryOffset += EntriesBase;
634 return {
Section.StringSection,
Index, StringOffset, EntryOffset};
639 assert(Bucket < Hdr.BucketCount);
640 uint32_t BucketOffset = BucketsBase + 4 * Bucket;
641 return Section.AccelSection.getU32(&BucketOffset);
645 assert(0 < Index && Index <= Hdr.NameCount);
646 uint32_t HashOffset = HashesBase + 4 * (Index - 1);
647 return Section.AccelSection.getU32(&HashOffset);
657 auto EntryOr = getEntry(Offset);
680 while (dumpEntry(W, &EntryOffset))
684 void DWARFDebugNames::NameIndex::dumpCUs(
ScopedPrinter &W)
const {
685 ListScope CUScope(W,
"Compilation Unit offsets");
690 void DWARFDebugNames::NameIndex::dumpLocalTUs(
ScopedPrinter &W)
const {
691 if (Hdr.LocalTypeUnitCount == 0)
694 ListScope TUScope(W,
"Local Type Unit offsets");
695 for (
uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
696 W.
startLine() <<
format(
"LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU));
699 void DWARFDebugNames::NameIndex::dumpForeignTUs(
ScopedPrinter &W)
const {
700 if (Hdr.ForeignTypeUnitCount == 0)
703 ListScope TUScope(W,
"Foreign Type Unit signatures");
704 for (
uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
706 getForeignTUSignature(TU));
710 void DWARFDebugNames::NameIndex::dumpAbbreviations(
ScopedPrinter &W)
const {
711 ListScope AbbrevsScope(W,
"Abbreviations");
712 for (
const auto &Abbr : Abbrevs)
716 void DWARFDebugNames::NameIndex::dumpBucket(
ScopedPrinter &W,
724 if (Index > Hdr.NameCount) {
729 for (; Index <= Hdr.NameCount; ++
Index) {
730 uint32_t Hash = getHashArrayEntry(Index);
731 if (Hash % Hdr.BucketCount != Bucket)
734 dumpName(W, getNameTableEntry(Index), Hash);
744 dumpAbbreviations(W);
746 if (Hdr.BucketCount > 0) {
747 for (
uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
748 dumpBucket(W, Bucket);
752 W.
startLine() <<
"Hash table not present\n";
754 dumpName(W, NTE,
None);
764 NameIndices.push_back(std::move(Next));
781 DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
782 const Header &Hdr = CurrentIndex->Hdr;
783 if (Hdr.BucketCount == 0) {
796 uint32_t Bucket = *Hash % Hdr.BucketCount;
801 for (; Index <= Hdr.NameCount; ++
Index) {
802 uint32_t Hash = CurrentIndex->getHashArrayEntry(Index);
803 if (Hash % Hdr.BucketCount != Bucket)
813 bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
814 auto EntryOr = CurrentIndex->getEntry(&DataOffset);
819 CurrentEntry = std::move(*EntryOr);
823 bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
828 return getEntryAtCurrentOffset();
831 void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
832 for (
const NameIndex *End = CurrentIndex->Section.NameIndices.end();
833 CurrentIndex != End; ++CurrentIndex) {
834 if (findInCurrentIndex())
840 void DWARFDebugNames::ValueIterator::next() {
841 assert(CurrentIndex &&
"Incrementing an end() iterator?");
844 if (getEntryAtCurrentOffset())
848 if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
855 searchFromStartOfCurrentIndex();
860 : CurrentIndex(AccelTable.NameIndices.
begin()), IsLocal(
false), Key(Key) {
861 searchFromStartOfCurrentIndex();
866 : CurrentIndex(&NI), IsLocal(
true), Key(Key) {
867 if (!findInCurrentIndex())
873 if (NameIndices.empty())
880 if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
881 for (
const auto &NI : *
this) {
883 CUToNameIndex.try_emplace(NI.getCUOffset(
CU), &NI);
886 return CUToNameIndex.lookup(CUOffset);
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
uint32_t getEntryOffset() const
Returns the offset of the first Entry in the list.
void dump(ScopedPrinter &W) const
uint32_t getNextUnitOffset() const
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in the accelerator table matching Key.
This class represents lattice values for constants.
StringRef AtomTypeString(unsigned Atom)
std::vector< AttributeEncoding > Attributes
List of index attributes.
SmallVector< DWARFFormValue, 3 > Values
Optional< DWARFFormValue > lookup(dwarf::Index Index) const
Returns the value of the Index Attribute in this Accelerator Entry, if the Entry contains such Attrib...
static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc()
void push_back(const T &Elt)
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
uint32_t getStringOffset() const
Returns the offset of the name of the described entities.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
static void dump(StringRef Title, SpillInfo const &Spills)
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
block Block Frequency true
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Optional< DWARFFormValue > lookup(HeaderData::AtomType Atom) const
Returns the value of the Atom in this Accelerator Entry, if the Entry contains such Atom...
Base class for error info classes.
Abbreviation describing the encoding of Name Index entries.
uint64_t getForeignTUSignature(uint32_t TU) const
Reads signature of foreign type unit TU. TU is 0-based.
const NameIndex * getCUNameIndex(uint32_t CUOffset)
Return the Name Index covering the compile unit at CUOffset, or nullptr if there is no Name Index cov...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
DWARFDataExtractor AccelSection
llvm::Error extract() override
Tagged union holding either a T or a Error.
Index attribute and its encoding.
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
dwarf::Tag Tag
Dwarf Tag of the described entity.
raw_ostream & getOStream()
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Represents a single accelerator table within the Dwarf 5 .debug_names section.
Optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or None if the Comp...
uint32_t getBucketArrayEntry(uint32_t Bucket) const
Reads an entry in the Bucket Array for the given Bucket.
Optional< uint64_t > getCUIndex() const
Returns the Index into the Compilation Unit list of the owning Name Index or None if this Accelerator...
static DWARFDebugNames::Abbrev sentinelAbbrev()
static Atom formatAtom(unsigned Atom)
DWARF v5-specific implementation of an Accelerator Entry.
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
const uint32_t DW_INVALID_OFFSET
Identifier of an invalid DIE offset in the .debug_info section.
virtual ~DWARFAcceleratorTable()
ValueIterator()=default
End marker.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
raw_ostream & startLine()
Optional< uint64_t > getDIEUnitOffset() const
Returns the Offset of the DIE within the containing CU or TU.
#define offsetof(TYPE, MEMBER)
NameTableEntry getNameTableEntry(uint32_t Index) const
Reads an entry in the Name Table for the given Index.
uint32_t getHashArrayEntry(uint32_t Index) const
Reads an entry in the Hash Array for the given Index.
void printHex(StringRef Label, T Value)
Expected< Entry > getEntry(uint32_t *Offset) const
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 consumeError(Error Err)
Consume a Error without doing anything.
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
uint32_t getLocalTUOffset(uint32_t TU) const
Reads offset of local type unit TU, TU is 0-based.
static const char *const Magic
void printString(StringRef Value)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
const char * getString() const
Return the string referenced by this name table entry or nullptr if the string offset is not valid...
.debug_names section consists of one or more units.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
static ErrorSuccess success()
Create a success value.
void printNumber(StringRef Label, uint64_t Value)
void dump(ScopedPrinter &W) const
A single entry in the Name Table (Dwarf 5 sect.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
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...
void dump(raw_ostream &OS) const override
static Twine utohexstr(const uint64_t &Val)
uint32_t getIndex() const
Return the index of this name in the parent Name Index.
A range adaptor for a pair of iterators.
This file contains constants used for implementing Dwarf debug support.
std::pair< uint32_t, dwarf::Tag > readAtoms(uint32_t &HashDataOffset)
Return information related to the DWARF DIE we're looking for when performing a lookup by name...
Optional< uint64_t > getDIESectionOffset() const
Returns the Section Offset of the Debug Info Entry associated with this Accelerator Entry or None if ...
Error returned by NameIndex::getEntry to report it has reached the end of the entry list...
StringRef AtomValueString(uint16_t Atom, unsigned Val)
Returns the symbolic string representing Val when used as a value for atom Atom.
Optional< uint64_t > getCUOffset() const override
Returns the Offset of the Compilation Unit associated with this Accelerator Entry or None if the Comp...
void dump(ScopedPrinter &W) const
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
ValueIterator()=default
End marker.
void dump(raw_ostream &OS) const override
uint32_t getCUCount() const
uint32_t Code
Abbreviation code.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE)
LLVM Value Representation.
Lightweight error class with error context and mandatory checking.
This class implements an extremely fast bulk output stream that can only output to a stream...
Optional< dwarf::Tag > getTag() const override
Returns the Tag of the Debug Info Entry associated with this Accelerator Entry or None if the Tag is ...
StringRef - Represent a constant reference to a string, i.e.
llvm::Error extract() override
Marker as the end of a list of atoms.
for(unsigned i=Desc.getNumOperands(), e=OldMI.getNumOperands();i !=e;++i)
uint32_t getCUOffset(uint32_t CU) const
Reads offset of compilation unit CU. CU is 0-based.
iterator_range< ValueIterator > equal_range(StringRef Key) const
Look up all entries in this Name Index matching Key.
DataExtractor StringSection
uint32_t getHeaderDataLength()
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...