33 using namespace dwarf;
39 addUnitsImpl(
C,
D,
Section,
C.getDebugAbbrev(), &
D.getRangesSection(),
40 &
D.getLocSection(),
D.getStrSection(),
41 D.getStrOffsetsSection(), &
D.getAddrSection(),
42 D.getLineSection(),
D.isLittleEndian(),
false,
false,
51 addUnitsImpl(
C,
D, DWOSection,
C.getDebugAbbrevDWO(), &
D.getRangesDWOSection(),
52 &
D.getLocDWOSection(),
D.getStrDWOSection(),
53 D.getStrOffsetsDWOSection(), &
D.getAddrSection(),
54 D.getLineDWOSection(),
C.isLittleEndian(),
true, Lazy,
58 void DWARFUnitVector::addUnitsImpl(
71 -> std::unique_ptr<DWARFUnit> {
79 if (!IndexEntry && IsDWO) {
86 std::unique_ptr<DWARFUnit> U;
88 U = std::make_unique<DWARFTypeUnit>(
Context, InfoSection, Header, DA,
89 RS, LocSection,
SS, SOS, AOS,
LS,
92 U = std::make_unique<DWARFCompileUnit>(
Context, InfoSection, Header,
93 DA, RS, LocSection,
SS, SOS,
94 AOS,
LS,
LE, IsDWO, *
this);
108 if (
I != this->
end() &&
109 (&(*I)->getInfoSection() != &Section || (*I)->getOffset() ==
Offset)) {
117 Offset = U->getNextUnitOffset();
124 [](
const std::unique_ptr<DWARFUnit> &LHS,
125 const std::unique_ptr<DWARFUnit> &RHS) {
126 return LHS->getOffset() < RHS->getOffset();
128 return this->insert(
I,
std::move(Unit))->get();
132 auto end =
begin() + getNumInfoUnits();
135 [](uint64_t LHS,
const std::unique_ptr<DWARFUnit> &RHS) {
136 return LHS < RHS->getNextUnitOffset();
145 const auto *CUOff =
E.getContribution(DW_SECT_INFO);
149 auto Offset = CUOff->Offset;
150 auto end =
begin() + getNumInfoUnits();
154 [](uint64_t LHS,
const std::unique_ptr<DWARFUnit> &RHS) {
155 return LHS < RHS->getNextUnitOffset();
163 auto U = Parser(
Offset, DW_SECT_INFO,
nullptr, &
E);
167 auto *NewCU = U.get();
180 RangeSection(RS), LineSection(
LS), StringSection(
SS),
181 StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(
LE),
182 IsDWO(IsDWO), UnitVector(UnitVector) {
196 auto R =
Context.info_section_units();
202 if (
I != R.end() && std::next(
I) == R.end())
203 return (*I)->getAddrOffsetSectionItem(
Index);
205 if (!AddrOffsetSectionBase)
218 if (!StringOffsetsTableContribution)
226 return DA.getRelocatedValue(ItemSize, &
Offset);
231 uint64_t *offset_ptr,
233 Offset = *offset_ptr;
235 IndexEntry =
nullptr;
256 TypeHash = debug_info.
getU64(offset_ptr, &Err);
260 DWOId = debug_info.
getU64(offset_ptr, &Err);
266 assert(*offset_ptr - Offset <= 255 &&
"unexpected header size");
267 Size = uint8_t(*offset_ptr - Offset);
274 : TypeOffset >= Size &&
280 if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
294 auto *UnitContrib = IndexEntry->getContribution();
298 auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
301 AbbrOffset = AbbrEntry->Offset;
307 template<
typename ListTableType>
318 " list table with base = 0x%" PRIx64
"\n",
323 if (
Error E = Table.extractHeaderAndOffsets(DA, &
Offset))
331 assert(!DieArray.empty());
334 uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
335 return RangeList.
extract(RangesData, &ActualRangeListOffset);
341 RangeSectionBase = 0;
343 AddrOffsetSectionBase =
None;
352 void DWARFUnit::extractDIEsToVector(
353 bool AppendCUDie,
bool AppendNonCUDies,
354 std::vector<DWARFDebugInfoEntry> &Dies)
const {
355 if (!AppendCUDie && !AppendNonCUDies)
367 while (
DIE.extractFast(*
this, &DIEOffset, DebugInfoData, NextCUOffset,
372 if (!AppendNonCUDies)
377 Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
384 DIE.getAbbreviationDeclarationPtr()) {
386 if (AbbrDecl->hasChildren())
400 if (DIEOffset > NextCUOffset)
403 "DWARF compile unit extends beyond its " 404 "bounds cu 0x%8.8" PRIx64
" " 405 "at 0x%8.8" PRIx64
"\n",
409 void DWARFUnit::extractDIEsIfNeeded(
bool CUDieOnly) {
415 if ((CUDieOnly && !DieArray.empty()) ||
419 bool HasCUDie = !DieArray.empty();
420 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
422 if (DieArray.empty())
429 DWARFDie UnitDie(
this, &DieArray[0]);
434 assert(RangeSectionBase == 0);
435 assert(LocSectionBase == 0);
437 if (!AddrOffsetSectionBase)
438 AddrOffsetSectionBase =
454 auto StringOffsetOrError =
457 if (!StringOffsetOrError)
459 "invalid reference to or invalid content in " 460 ".debug_str_offsets[.dwo]: " +
461 toString(StringOffsetOrError.takeError()));
463 StringOffsetsTableContribution = *StringOffsetOrError;
471 uint64_t ContributionBaseOffset = 0;
473 if (
auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
474 ContributionBaseOffset = Contrib->Offset;
476 &
Context.getDWARFObj().getRnglistsDWOSection(),
477 ContributionBaseOffset +
490 ?
Context.getDWARFObj().getLoclistsDWOSection().Data
491 :
Context.getDWARFObj().getLocDWOSection().Data;
493 if (
const auto *
C = IndexEntry->getContribution(
499 std::make_unique<DWARFDebugLoclists>(DWARFData, Header.
getVersion());
502 LocTable = std::make_unique<DWARFDebugLoclists>(
504 Context.getDWARFObj().getLoclistsSection(),
518 bool DWARFUnit::parseDWO() {
541 auto DWOContext =
Context.getDWOContext(AbsolutePath);
548 DWO = std::shared_ptr<DWARFCompileUnit>(
std::move(DWOContext), DWOCU);
550 if (AddrOffsetSectionBase)
551 DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
553 DWO->setRangesSection(&
Context.getDWARFObj().getRnglistsDWOSection(),
557 DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
563 void DWARFUnit::clearDIEs(
bool KeepCUDie) {
564 if (DieArray.size() > (
unsigned)KeepCUDie) {
565 DieArray.resize((
unsigned)KeepCUDie);
566 DieArray.shrink_to_fit();
581 auto RangeListOrError = RnglistTable.
findList(RangesData,
Offset);
582 if (RangeListOrError)
583 return RangeListOrError.get().getAbsoluteRanges(
getBaseAddress(), *
this);
584 return RangeListOrError.takeError();
593 "invalid range list table index %d (possibly " 594 "missing the entire range list table)",
605 if (!CUDIERangesOrError)
607 "decoding address ranges: %s",
609 return *CUDIERangesOrError;
625 InterpretationError =
627 return !InterpretationError;
639 if (DIERangesOrError) {
640 for (
const auto &R : DIERangesOrError.get()) {
642 if (R.LowPC == R.HighPC)
644 auto B = AddrDieMap.upper_bound(R.LowPC);
645 if (
B != AddrDieMap.begin() && R.LowPC < (--
B)->second.first) {
648 if (R.HighPC <
B->second.first)
649 AddrDieMap[R.HighPC] =
B->second;
650 if (R.LowPC >
B->first)
651 AddrDieMap[
B->first].first = R.LowPC;
653 AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
668 extractDIEsIfNeeded(
false);
669 if (AddrDieMap.empty())
671 auto R = AddrDieMap.upper_bound(
Address);
672 if (R == AddrDieMap.begin())
676 if (
Address >= R->second.first)
678 return R->second.second;
696 if (SubroutineDIE.
getTag() == DW_TAG_inlined_subroutine)
698 SubroutineDIE = SubroutineDIE.
getParent();
705 if (
Kind == DW_SECT_INFO)
723 for (
uint32_t I = getDIEIndex(Die) - 1;
I > 0; --
I) {
724 if (DieArray[
I].
getDepth() == ParentDepth)
742 for (
size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size();
I < EndIdx;
759 for (
size_t I = getDIEIndex(Die);
I > 0;) {
774 size_t I = getDIEIndex(Die) + 1;
775 if (
I >= DieArray.size())
785 for (
size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size();
I < EndIdx;
788 DieArray[
I].getTag() == dwarf::DW_TAG_null)
817 uint64_t ValidationSize =
alignTo(
Size, EntrySize);
819 if (ValidationSize >=
Size)
873 return DescOrError.takeError();
882 return DescOrError.takeError();
899 return DescOrError.takeError();
909 IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) :
nullptr;
919 return DescOrError.takeError();
929 else if (!IndexEntry && !StringOffsetSection.
Data.
empty())
936 return DescOrError.takeError();
947 return *Off + RangeSectionBase;
954 return *Off + LocSectionBase;
const DWARFAbbreviationDeclarationSet * getAbbreviations() const
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.
uint64_t getNextUnitOffset() const
static Expected< StrOffsetsContributionDescriptor > parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, llvm::dwarf::DwarfFormat Format, uint64_t Offset)
Error visitAbsoluteLocationList(uint64_t Offset, Optional< object::SectionedAddress > BaseAddr, std::function< Optional< object::SectionedAddress >(uint32_t)> LookupAddr, function_ref< bool(Expected< DWARFLocationExpression >)> Callback) const
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
DWARFUnit * getUnitForOffset(uint64_t Offset) const
Optional< uint64_t > getRnglistOffset(uint32_t Index)
Return a rangelist's offset based on an index.
Expected< Optional< StrOffsetsContributionDescriptor > > determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form.
This class represents lattice values for constants.
Represents base address of the CU.
static Expected< StrOffsetsContributionDescriptor > parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset)
LLVM_NODISCARD bool empty() const
void push_back(const T &Elt)
uint8_t getDwarfOffsetByteSize() const
dwarf::DwarfFormat getFormat() const
DWARFDie getSibling(const DWARFDebugInfoEntry *Die)
Expected< StrOffsetsContributionDescriptor > validateContributionSize(DWARFDataExtractor &DA)
Determine whether a contribution to the string offsets table is consistent with the relevant section ...
uint8_t getDwarfStringOffsetsByteSize() const
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind)
Read units from a .debug_info or .debug_types section.
DWARFDie getParent() const
Get the parent of this DIE object.
DWARFDie getSubroutineForAddress(uint64_t Address)
Returns subprogram DIE with address range encompassing the provided address.
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
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
const char * getCompilationDir()
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.
Optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Tagged union holding either a T or a Error.
uint64_t Size
The contribution size not including the header.
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
uint8_t getAddressByteSize() const
Optional< object::SectionedAddress > toSectionedAddress(const Optional< DWARFFormValue > &V)
Optional< uint64_t > getLoclistOffset(uint32_t Index)
DWARFAddressRangesVector getAbsoluteRanges(llvm::Optional< object::SectionedAddress > BaseAddr) const
getAbsoluteRanges - Returns absolute address ranges defined by this range list.
LLVM_NODISCARD size_t size() const
size - Get the string size.
llvm::Optional< object::SectionedAddress > getBaseAddress()
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
uint32_t getDepth() const
DWARFDie getLastChild(const DWARFDebugInfoEntry *Die)
uint16_t getVersion() const
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)
Optional< uint64_t > toSectionOffset(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
static unsigned getDepth(const SmallVectorImpl< const MachineBasicBlock * > &Stack, const MachineBasicBlock *MBB)
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")
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
A structured debug information entry.
Optional< uint64_t > getDWOId()
Expected< DWARFAddressRangesVector > collectAddressRanges()
Error tryExtractDIEsIfNeeded(bool CUDieOnly)
const DWARFAbbreviationDeclarationSet * getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
DWARFDie getParent(const DWARFDebugInfoEntry *Die)
SectionKind - This is a simple POD value that classifies the properties of a section.
Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr)
uint32_t getHeaderSize() const
Size in bytes of the parsed unit header.
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
Error extractRangeList(uint64_t RangeListOffset, DWARFDebugRangeList &RangeList) const
Extract the range list referenced by this compile unit from the .debug_ranges section.
void consumeError(Error Err)
Consume a Error without doing anything.
const DWARFUnitIndex & getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind)
static Expected< ListTableType > parseListTableHeader(DWARFDataExtractor &DA, uint64_t Offset, DwarfFormat Format)
UnitType
Constants for unit types in DWARF v5.
DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E)
uint64_t getStringOffsetsBase() const
uint64_t getOffset() const
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
static ErrorSuccess success()
Create a success value.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
bool isSubroutineDIE() const
Returns true if DIE represents a subprogram or an inlined subroutine.
DWARFDie getFirstChild() const
Get the first child of this DIE object.
Expected< DWARFAddressRangesVector > findRnglistFromOffset(uint64_t Offset)
Return a vector of address ranges resulting from a (possibly encoded) range list starting at a given ...
static bool isAddressSizeSupported(unsigned AddressSize)
void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, DWARFSectionKind SectionKind, bool Lazy=false)
Read units from a .debug_info.dwo or .debug_types.dwo section.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Expected< Optional< StrOffsetsContributionDescriptor > > determineStringOffsetsTableContribution(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form.
Expected< DWARFListType > findList(DWARFDataExtractor Data, uint64_t Offset)
Look up a list based on a given offset.
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.
DWARFDataExtractor getDebugInfoExtractor() const
Optional< uint64_t > getRangesBaseAttribute() const
Extract the range base attribute from this DIE as absolute section offset.
static Expected< StrOffsetsContributionDescriptor > parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset)
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static bool isSupportedVersion(unsigned version)
const DWARFLocationTable & getLocationTable()
dwarf::Tag getTag() const
Error joinErrors(Error E1, Error E2)
Concatenate errors.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die)
void updateAddressDieMap(DWARFDie Die)
Recursively update address to Die map.
void setRangesSection(const DWARFSection *RS, uint64_t Base)
DWARFDie getSibling() const
Get the sibling of this DIE object.
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
DWARFDebugInfoEntry - A DIE with only the minimum required data.
Lightweight error class with error context and mandatory checking.
const Entry * getFromOffset(uint32_t Offset) const
Optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
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