35 using namespace dwarf;
60 void DWARFUnitVector::addUnitsImpl(
73 -> std::unique_ptr<DWARFUnit> {
82 if (!Header.
extract(Context, Data, &Offset, SectionKind, Index,
85 std::unique_ptr<DWARFUnit> U;
87 U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
88 RS, LocSection, SS, SOS, AOS, LS,
91 U = llvm::make_unique<DWARFCompileUnit>(
Context, InfoSection, Header,
92 DA, RS, LocSection, SS, SOS,
93 AOS,
LS,
LE, IsDWO, *
this);
107 if (
I != this->
end() &&
108 (&(*I)->getInfoSection() != &Section || (*I)->getOffset() ==
Offset)) {
112 auto U = Parser(Offset, SectionKind, &Section,
nullptr);
116 Offset = U->getNextUnitOffset();
117 I = std::next(this->insert(
I, std::move(U)));
123 [](
const std::unique_ptr<DWARFUnit> &LHS,
124 const std::unique_ptr<DWARFUnit> &RHS) {
125 return LHS->getOffset() < RHS->getOffset();
127 return this->insert(
I, std::move(Unit))->get();
131 auto end =
begin() + getNumInfoUnits();
134 [](
uint32_t LHS,
const std::unique_ptr<DWARFUnit> &RHS) {
135 return LHS < RHS->getNextUnitOffset();
148 auto Offset = CUOff->Offset;
149 auto end =
begin() + getNumInfoUnits();
153 [](
uint32_t LHS,
const std::unique_ptr<DWARFUnit> &RHS) {
154 return LHS < RHS->getNextUnitOffset();
166 auto *NewCU = U.get();
167 this->insert(
CU, std::move(U));
178 : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
179 RangeSection(RS), LocSection(LocSection), LineSection(LS),
180 StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
181 isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) {
210 if (
I != R.end() && std::next(
I) == R.end())
211 return (*I)->getAddrOffsetSectionItem(Index);
219 uint64_t
Address = DA.getRelocatedAddress(&Offset, &Section);
224 if (!StringOffsetsTableContribution)
228 if (StringOffsetSection.
Data.
size() < Offset + ItemSize)
232 return DA.getRelocatedValue(ItemSize, &Offset);
243 if (!IndexEntry && Index)
245 Length = debug_info.
getU32(offset_ptr);
247 unsigned SizeOfLength = 4;
253 AbbrOffset = debug_info.
getU32(offset_ptr);
267 auto *UnitContrib = IndexEntry->getOffset();
268 if (!UnitContrib || UnitContrib->Length != (Length + 4))
273 AbbrOffset = AbbrEntry->Offset;
276 TypeHash = debug_info.
getU64(offset_ptr);
277 TypeOffset = debug_info.
getU32(offset_ptr);
279 DWOId = debug_info.
getU64(offset_ptr);
282 assert(*offset_ptr -
Offset <= 255 &&
"unexpected header size");
290 : TypeOffset >=
Size && TypeOffset <
getLength() + SizeOfLength;
295 if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
313 " range list table with base = 0x%" PRIu32,
326 assert(!DieArray.empty());
329 uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
330 return RangeList.
extract(RangesData, &ActualRangeListOffset);
336 RangeSectionBase = 0;
337 AddrOffsetSectionBase = 0;
346 void DWARFUnit::extractDIEsToVector(
347 bool AppendCUDie,
bool AppendNonCUDies,
348 std::vector<DWARFDebugInfoEntry> &Dies)
const {
349 if (!AppendCUDie && !AppendNonCUDies)
361 while (DIE.
extractFast(*
this, &DIEOffset, DebugInfoData, NextCUOffset,
366 if (!AppendNonCUDies)
371 Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
380 if (AbbrDecl->hasChildren())
394 if (DIEOffset > NextCUOffset)
396 "bounds cu 0x%8.8x at 0x%8.8x\n",
400 size_t DWARFUnit::extractDIEsIfNeeded(
bool CUDieOnly) {
401 if ((CUDieOnly && !DieArray.empty()) ||
405 bool HasCUDie = !DieArray.empty();
406 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
408 if (DieArray.empty())
417 assert(AddrOffsetSectionBase == 0);
418 assert(RangeSectionBase == 0);
420 if (!AddrOffsetSectionBase)
421 AddrOffsetSectionBase =
436 StringOffsetsTableContribution =
439 StringOffsetsTableContribution =
455 if (
auto TableOrError =
457 RngListTable = TableOrError.get();
460 <<
toString(TableOrError.takeError())
465 if (IsDWO && RngListTable)
466 RangeSectionBase = RngListTable->getHeaderSize();
474 return DieArray.size();
477 bool DWARFUnit::parseDWO() {
505 DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
507 DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
513 DWO->RngListTable = TableOrError.get();
516 <<
toString(TableOrError.takeError())
518 if (DWO->RngListTable)
519 DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
522 DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
528 void DWARFUnit::clearDIEs(
bool KeepCUDie) {
529 if (DieArray.size() > (
unsigned)KeepCUDie) {
530 DieArray.resize((
unsigned)KeepCUDie);
531 DieArray.shrink_to_fit();
545 isLittleEndian, RngListTable->getAddrSize());
546 auto RangeListOrError = RngListTable->findList(RangesData, Offset);
547 if (RangeListOrError)
548 return RangeListOrError.get().getAbsoluteRanges(
getBaseAddress(), *
this);
549 return RangeListOrError.takeError();
553 "missing or invalid range list table");
563 "invalid range list table index %d", Index);
566 "missing or invalid range list table");
576 if (!CUDIERangesOrError)
578 "decoding address ranges: %s",
580 return *CUDIERangesOrError;
586 if (DIERangesOrError) {
587 for (
const auto &R : DIERangesOrError.get()) {
589 if (R.LowPC == R.HighPC)
591 auto B = AddrDieMap.upper_bound(R.LowPC);
592 if (
B != AddrDieMap.begin() && R.LowPC < (--
B)->
second.first) {
595 if (R.HighPC <
B->second.first)
596 AddrDieMap[R.HighPC] =
B->second;
597 if (R.LowPC >
B->first)
598 AddrDieMap[
B->first].first = R.LowPC;
600 AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
615 extractDIEsIfNeeded(
false);
616 if (AddrDieMap.empty())
618 auto R = AddrDieMap.upper_bound(Address);
619 if (R == AddrDieMap.begin())
623 if (Address >= R->second.first)
625 return R->second.second;
643 if (SubroutineDIE.
getTag() == DW_TAG_inlined_subroutine)
645 SubroutineDIE = SubroutineDIE.
getParent();
669 const uint32_t ParentDepth = Depth - 1;
670 for (
uint32_t I = getDIEIndex(Die) - 1;
I > 0; --
I) {
671 if (DieArray[
I].getDepth() == ParentDepth)
689 for (
size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size();
I < EndIdx;
691 if (DieArray[
I].getDepth() ==
Depth)
706 for (
size_t I = getDIEIndex(Die);
I > 0;) {
708 if (DieArray[
I].getDepth() == Depth - 1)
710 if (DieArray[
I].getDepth() == Depth)
721 size_t I = getDIEIndex(Die) + 1;
722 if (I >= DieArray.size())
724 return DWARFDie(
this, &DieArray[I]);
732 for (
size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size();
I < EndIdx;
734 if (DieArray[
I].getDepth() == Depth + 1 &&
735 DieArray[
I].getTag() == dwarf::DW_TAG_null)
737 assert(DieArray[I].getDepth() > Depth &&
"Not processing children?");
764 uint64_t ValidationSize =
alignTo(
Size, EntrySize);
766 if (ValidationSize >=
Size)
779 if (DA.
getU32(&Offset) != 0xffffffff)
797 if (ContributionSize >= 0xfffffff0)
815 if (!Descriptor &&
Offset >= 8)
834 return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
842 return {{
C->Offset,
C->Length, 4,
DWARF32}};
const DWARFAbbreviationDeclarationSet * getAbbreviations() const
const DWARFUnitIndex & getTUIndex()
void getInlinedChainForAddress(uint64_t Address, SmallVectorImpl< DWARFDie > &InlinedChain)
getInlinedChainForAddress - fetches inlined chain for a given address.
const_iterator end(StringRef path)
Get end iterator over path.
virtual const DWARFSection & getAddrSection() const
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
virtual const DWARFSection & getLocDWOSection() const
This class represents lattice values for constants.
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
void push_back(const T &Elt)
std::shared_ptr< DWARFContext > getDWOContext(StringRef AbsolutePath)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
virtual const DWARFSection & getLocSection() const
DWARFDie getSibling(const DWARFDebugInfoEntry *Die)
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static Optional< StrOffsetsContributionDescriptor > parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset)
Optional< StrOffsetsContributionDescriptor > validateContributionSize(DWARFDataExtractor &DA)
Determine whether a contribution to the string offsets table is consistent with the relevant section ...
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...
virtual const DWARFSection & getRnglistsDWOSection() const
block Block Frequency true
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
uint8_t getDwarfStringOffsetsByteSize() const
void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind)
Read units from a .debug_info or .debug_types section.
DWARFDie getSubroutineForAddress(uint64_t Address)
Returns subprogram DIE with address range encompassing the provided address.
static Optional< StrOffsetsContributionDescriptor > parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset)
virtual bool isLittleEndian() const =0
uint32_t getNextUnitOffset() const
Optional< StrOffsetsContributionDescriptor > determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form...
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
DWARFUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector)
std::string toString(Error E)
Write all error messages (if any) in E to a string.
static ManagedStatic< DebugCounter > DC
Optional< StrOffsetsContributionDescriptor > determineStringOffsetsTableContribution(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form...
const char * getCompilationDir()
Optional< uint64_t > getRangesBaseAttribute() const
Extract the range base attribute from this DIE as absolute section offset.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
DWARFUnit * addUnit(std::unique_ptr< DWARFUnit > Unit)
Add an existing DWARFUnit to this UnitVector.
Error extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const
Extract the range list referenced by this compile unit from the .debug_ranges section.
Tagged union holding either a T or a Error.
virtual const DWARFSection & getStringOffsetDWOSection() const
uint8_t getAddressByteSize() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
const DWARFDebugAbbrev * getDebugAbbrev()
Get a pointer to the parsed DebugAbbrev object.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
uint32_t getDepth() const
DWARFDie getLastChild(const DWARFDebugInfoEntry *Die)
uint16_t getVersion() const
DWARFDie getSibling() const
Get the sibling of this DIE object.
Expected< DWARFAddressRangesVector > findRnglistFromIndex(uint32_t Index)
Return a vector of address ranges retrieved from an encoded range list whose offset is found via a ta...
DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die)
unit_iterator_range info_section_units()
Get units from .debug_info in this context.
Optional< uint64_t > toSectionOffset(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
virtual const DWARFSection & getStringOffsetSection() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A structured debug information entry.
bool isSubroutineDIE() const
Returns true if DIE represents a subprogram or an inlined subroutine.
Optional< uint64_t > getDWOId()
Expected< DWARFAddressRangesVector > collectAddressRanges()
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr)
Extracts a debug info entry, which is a child of a given unit, starting at a given offset...
const DWARFAbbreviationDeclarationSet * getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
DWARFDie getParent(const DWARFDebugInfoEntry *Die)
virtual const DWARFSection & getLineDWOSection() const
SectionKind - This is a simple POD value that classifies the properties of a section.
virtual StringRef getStringSection() const
void setRangesSection(const DWARFSection *RS, uint32_t Base)
virtual StringRef getStringDWOSection() const
uint32_t getHeaderSize() const
Size in bytes of the parsed unit header.
void consumeError(Error Err)
Consume a Error without doing anything.
const DWARFUnitIndex & getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind)
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
DWARFUnit * getUnitForOffset(uint32_t Offset) const
DWARFAddressRangesVector getAbsoluteRanges(llvm::Optional< SectionedAddress > BaseAddr) const
getAbsoluteRanges - Returns absolute address ranges defined by this range list.
UnitType
Constants for unit types in DWARF v5.
DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E)
uint64_t getStringOffsetsBase() const
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
static Expected< DWARFDebugRnglistTable > parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset)
void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, DWARFSectionKind SectionKind, bool Lazy=false)
Read units from a .debug_info.dwo or .debug_types.dwo section.
Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr)
Extract the table header and the array of offsets.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Describe a collection of units.
Optional< const char * > toString(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
virtual const DWARFSection & getRnglistsSection() const
uint32_t getLength() const
DWARFDataExtractor getDebugInfoExtractor() const
virtual const DWARFSection & getLineSection() const
static bool isSupportedVersion(unsigned version)
virtual const DWARFSection & getRangeDWOSection() const
dwarf::Tag getTag() const
LLVM_NODISCARD bool empty() const
Expected< DWARFAddressRangesVector > findRnglistFromOffset(uint32_t Offset)
Return a vector of address ranges resulting from a (possibly encoded) range list starting at a given ...
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
uint32_t getOffset() const
Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die)
void updateAddressDieMap(DWARFDie Die)
Recursively update address to Die map.
Optional< SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
bool isLittleEndian() const
const DWARFObject & getDWARFObj() const
const DWARFUnitIndex & getCUIndex()
llvm::Optional< SectionedAddress > getBaseAddress()
virtual const DWARFSection & getRangeSection() const
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
DWARFDebugInfoEntry - A DIE with only the minimum required data.
DWARFDie getFirstChild() const
Get the first child of this DIE object.
Lightweight error class with error context and mandatory checking.
const Entry * getFromOffset(uint32_t Offset) const
const SectionContribution * getOffset(DWARFSectionKind Sec) const
StringRef - Represent a constant reference to a string, i.e.
Optional< uint32_t > getRnglistOffset(uint32_t Index)
Return a rangelist's offset based on an index.
uint8_t getDwarfOffsetByteSize() const
void setMaxVersionIfGreater(unsigned Version)
Optional< uint64_t > toUnsigned(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Optional< uint64_t > getStringOffsetSectionItem(uint32_t Index) const
DWARFDie getParent() const
Get the parent of this DIE object.
Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr)
Optional< SectionedAddress > toSectionedAddress(const Optional< DWARFFormValue > &V)