1//===- DWARFUnit.cpp ------------------------------------------------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 46 addUnitsImpl(
C,
D, Section,
C.getDebugAbbrev(), &
D.getRangesSection(),
47 &
D.getLocSection(),
D.getStrSection(),
48D.getStrOffsetsSection(), &
D.getAddrSection(),
49D.getLineSection(),
D.isLittleEndian(),
false,
false,
58 addUnitsImpl(
C,
D, DWOSection,
C.getDebugAbbrevDWO(), &
D.getRangesDWOSection(),
59 &
D.getLocDWOSection(),
D.getStrDWOSection(),
60D.getStrOffsetsDWOSection(), &
D.getAddrSection(),
61D.getLineDWOSection(),
C.isLittleEndian(),
true, Lazy,
65void DWARFUnitVector::addUnitsImpl(
72// Lazy initialization of Parser, now that we have all section info. 74 Parser = [=, &Context, &Obj, &Section, &SOS,
78 -> std::unique_ptr<DWARFUnit> {
79constDWARFSection &InfoSection = CurSection ? *CurSection : Section;
89if (!IndexEntry && IsDWO) {
93if (Header.isTypeUnit())
94 IndexEntry =
Index.getFromHash(Header.getTypeHash());
95elseif (
auto DWOId = Header.getDWOId())
96 IndexEntry =
Index.getFromHash(*DWOId);
99 IndexEntry =
Index.getFromOffset(Header.getOffset());
102if (
Error ApplicationErr = Header.applyIndexEntry(IndexEntry)) {
107 std::unique_ptr<DWARFUnit>
U;
108if (Header.isTypeUnit())
109 U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
110 RS, LocSection, SS, SOS, AOS, LS,
113U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header,
114 DA, RS, LocSection, SS, SOS,
115 AOS, LS, LE, IsDWO, *
this);
121// Find a reasonable insertion point within the vector. We skip over 122// (a) units from a different section, (b) units from the same section 123// but with lower offset-within-section. This keeps units in order 124// within a section, although not necessarily within the object file, 125// even if we do lazy parsing. 129if (
I != this->
end() &&
130 (&(*I)->getInfoSection() != &Section || (*I)->getOffset() ==
Offset)) {
135// If parsing failed, we're done with this section. 139I = std::next(this->
insert(
I, std::move(U)));
145 [](
const std::unique_ptr<DWARFUnit> &
LHS,
146const std::unique_ptr<DWARFUnit> &
RHS) {
147returnLHS->getOffset() <
RHS->getOffset();
149return this->
insert(
I, std::move(Unit))->get();
157returnLHS <
RHS->getNextUnitOffset();
174 std::upper_bound(
begin(),
end, CUOff->getOffset(),
176 return LHS < RHS->getNextUnitOffset();
184auto U = Parser(
Offset, DW_SECT_INFO,
nullptr, &E);
188auto *NewCU = U.get();
200 : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
201 RangeSection(RS), LineSection(LS), StringSection(SS),
202 StringOffsetSection(SOS), AddrOffsetSection(AOS), IsLittleEndian(LE),
203 IsDWO(IsDWO), UnitVector(UnitVector) {
214std::optional<object::SectionedAddress>
216if (!AddrOffsetSectionBase) {
218// Surprising if a DWO file has more than one skeleton unit in it - this 219// probably shouldn't be valid, but if a use case is found, here's where to 220// support it (probably have to linearly search for the matching skeleton CU 223return (*R.begin())->getAddrOffsetSectionItem(
Index);
239if (!StringOffsetsTableContribution)
240return make_error<StringError>(
241"DW_FORM_strx used without a valid string offsets table",
246return make_error<StringError>(
"DW_FORM_strx uses index " +
Twine(
Index) +
247", which is too large",
251return DA.getRelocatedValue(ItemSize, &
Offset);
258 Offset = *offset_ptr;
273// Fake a unit type based on the section type. This isn't perfect, 274// but distinguishing compile and type units is generally enough. 281 TypeHash = debug_info.
getU64(offset_ptr, &Err);
285 DWOId = debug_info.
getU64(offset_ptr, &Err);
291"DWARF unit at 0x%8.8" PRIx64
" cannot be parsed:", Offset),
294// Header fields all parsed, capture the size of this unit header. 295assert(*offset_ptr - Offset <= 255 &&
"unexpected header size");
296 Size =
uint8_t(*offset_ptr - Offset);
301"DWARF unit from offset 0x%8.8" PRIx64
" incl. " 302"to offset 0x%8.8" PRIx64
" excl. " 303"extends past section size 0x%8.8zx",
304 Offset, NextCUOffset, debug_info.
size());
309"DWARF unit at offset 0x%8.8" PRIx64
" " 310"has unsupported version %" PRIu16
", supported are 2-%u",
313// Type offset is unit-relative; should be after the header and before 314// the end of the current unit. 317"DWARF type unit at offset " 319"has its relocated type_offset 0x%8.8" PRIx64
" " 320"pointing inside the header",
321 Offset, Offset + TypeOffset);
326"DWARF type unit from offset 0x%8.8" PRIx64
" incl. " 327"to offset 0x%8.8" PRIx64
" excl. has its " 328"relocated type_offset 0x%8.8" PRIx64
" pointing past the unit end",
329 Offset, NextCUOffset, Offset + TypeOffset);
333"DWARF unit at offset 0x%8.8" PRIx64, Offset))
336// Keep track of the highest DWARF version we encounter across all units. 347"DWARF package unit at offset 0x%8.8" PRIx64
348" has a non-zero abbreviation offset",
354"DWARF package unit at offset 0x%8.8" PRIx64
355" has no contribution index",
359if (UnitContrib->getLength() != IndexLength)
361"DWARF package unit at offset 0x%8.8" PRIx64
362" has an inconsistent index (expected: %" PRIu64
363", actual: %" PRIu64
")",
364 Offset, UnitContrib->getLength(), IndexLength);
369"DWARF package unit at offset 0x%8.8" PRIx64
370" missing abbreviation column",
373 AbbrOffset = AbbrEntry->getOffset();
379// Require that compile unit is extracted. 383uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
384return RangeList.
extract(RangesData, &ActualRangeListOffset);
390 RangeSectionBase = 0;
392 AddrOffsetSectionBase = std::nullopt;
405void DWARFUnit::extractDIEsToVector(
406bool AppendCUDie,
bool AppendNonCUDies,
407 std::vector<DWARFDebugInfoEntry> &Dies)
const{
408if (!AppendCUDie && !AppendNonCUDies)
411// Set the offset to that of the first DIE and calculate the start of the 412// next compilation unit header. 417// The end offset has been already checked by DWARFUnitHeader::extract. 419 std::vector<uint32_t> Parents;
420 std::vector<uint32_t> PrevSiblings;
424 ((AppendCUDie && Dies.empty()) || (!AppendCUDie && Dies.size() == 1)) &&
425"Dies array is not empty");
427// Fill Parents and Siblings stacks with initial value. 428 Parents.push_back(UINT32_MAX);
430 Parents.push_back(0);
431 PrevSiblings.push_back(0);
433// Start to extract dies. 435assert(Parents.size() > 0 &&
"Empty parents stack");
436assert((Parents.back() == UINT32_MAX || Parents.back() <= Dies.size()) &&
437"Wrong parent index");
439// Extract die. Stop if any error occurred. 440if (!
DIE.extractFast(*
this, &DIEOffset, DebugInfoData, NextCUOffset,
444// If previous sibling is remembered then update it`s SiblingIdx field. 445if (PrevSiblings.back() > 0) {
446assert(PrevSiblings.back() < Dies.size() &&
447"Previous sibling index is out of Dies boundaries");
448 Dies[PrevSiblings.back()].setSiblingIdx(Dies.size());
451// Store die into the Dies vector. 457// The average bytes per DIE entry has been seen to be 458// around 14-20 so let's pre-reserve the needed memory for 459// our DIE entries accordingly. 460 Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
462// Remember last previous sibling. 463 PrevSiblings.back() = Dies.size();
468// Check for new children scope. 470DIE.getAbbreviationDeclarationPtr()) {
471if (AbbrDecl->hasChildren()) {
472if (AppendCUDie || !IsCUDie) {
473assert(Dies.size() > 0 &&
"Dies does not contain any die");
474Parents.push_back(Dies.size() - 1);
475 PrevSiblings.push_back(0);
478// Stop if we have single compile unit die w/o children. 481// NULL DIE: finishes current children scope. 483 PrevSiblings.pop_back();
489// Stop when compile unit die is removed from the parents stack. 493void DWARFUnit::extractDIEsIfNeeded(
bool CUDieOnly) {
499if ((CUDieOnly && !DieArray.empty()) ||
503bool HasCUDie = !DieArray.empty();
504 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
509// If CU DIE was just parsed, copy several attribute values from it. 513DWARFDie UnitDie(
this, &DieArray[0]);
514if (std::optional<uint64_t> DWOId =
516 Header.setDWOId(*DWOId);
518assert(AddrOffsetSectionBase == std::nullopt);
519assert(RangeSectionBase == 0);
520assert(LocSectionBase == 0);
522if (!AddrOffsetSectionBase)
523 AddrOffsetSectionBase =
529// In general, in DWARF v5 and beyond we derive the start of the unit's 530// contribution to the string offsets table from the unit DIE's 531// DW_AT_str_offsets_base attribute. Split DWARF units do not use this 532// attribute, so we assume that there is a contribution to the string 533// offsets table starting at offset 0 of the debug_str_offsets.dwo section. 534// In both cases we need to determine the format of the contribution, 535// which may differ from the unit's format. 539auto StringOffsetOrError =
542if (!StringOffsetOrError)
544"invalid reference to or invalid content in " 545".debug_str_offsets[.dwo]: " +
546toString(StringOffsetOrError.takeError()));
548 StringOffsetsTableContribution = *StringOffsetOrError;
551// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to 552// describe address ranges. 554// In case of DWP, the base offset from the index has to be added. 557if (
auto *IndexEntry = Header.getIndexEntry())
558if (
auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
559 ContributionBaseOffset = Contrib->getOffset();
562 ContributionBaseOffset +
568 Header.getFormat())));
572// If we are reading a package file, we need to adjust the location list 573// data based on the index entries. 577if (
auto *IndexEntry = Header.getIndexEntry())
578if (
constauto *
C = IndexEntry->getContribution(
580Data =
Data.substr(
C->getOffset(),
C->getLength());
584 std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
587 LocTable = std::make_unique<DWARFDebugLoclists>(
598// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 599// skeleton CU DIE, so that DWARF users not aware of it are not broken. 603bool DWARFUnit::parseDWO(
StringRef DWOAlternativeLocation) {
628// Use the alternative location to get the DWARF context for the DWO object. 629if (DWOAlternativeLocation.
empty())
631// If the alternative context does not correspond to the original DWO object 632// (different hashes), the below 'getDWOCompileUnitForHash' call will catch 633// the issue, with a returned null context. 642 DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
643 DWO->setSkeletonUnit(
this);
644// Share .debug_addr and .debug_ranges section with compile unit in .dwo 645if (AddrOffsetSectionBase)
646 DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
649 DWO->setRangesSection(RangeSection, DWORangesBase.value_or(0));
655void DWARFUnit::clearDIEs(
bool KeepCUDie) {
656// Do not use resize() + shrink_to_fit() to free memory occupied by dies. 657// shrink_to_fit() is a *non-binding* request to reduce capacity() to size(). 658// It depends on the implementation whether the request is fulfilled. 659// Create a new vector with a small capacity and assign it to the DieArray to 660// have previous contents freed. 661 DieArray = (KeepCUDie && !DieArray.empty())
662 ? std::vector<DWARFDebugInfoEntry>({DieArray[0]})
663 : std::vector<DWARFDebugInfoEntry>();
675 IsLittleEndian, Header.getAddressByteSize());
679return RangeListOrError.get().getAbsoluteRanges(
getBaseAddress(), *
this);
680return RangeListOrError.takeError();
689"invalid range list table index %d (possibly " 690"missing the entire range list table)",
699// First, check if unit DIE describes address ranges for the whole unit. 701if (!CUDIERangesOrError)
703"decoding address ranges: %s",
704toString(CUDIERangesOrError.takeError()).c_str());
705return *CUDIERangesOrError;
719 Result.push_back(std::move(*L));
721 InterpretationError =
722joinErrors(L.takeError(), std::move(InterpretationError));
723return !InterpretationError;
726if (ParseError || InterpretationError)
727returnjoinErrors(std::move(ParseError), std::move(InterpretationError));
735if (DIERangesOrError) {
736for (
constauto &R : DIERangesOrError.get()) {
737// Ignore 0-sized ranges. 738if (R.LowPC == R.HighPC)
740autoB = AddrDieMap.upper_bound(R.LowPC);
741if (
B != AddrDieMap.begin() && R.LowPC < (--
B)->second.first) {
742// The range is a sub-range of existing ranges, we need to split the 744if (R.HighPC <
B->second.first)
745 AddrDieMap[R.HighPC] =
B->second;
746if (R.LowPC >
B->first)
747 AddrDieMap[
B->first].first = R.LowPC;
749 AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
754// Parent DIEs are added to the AddrDieMap prior to the Children DIEs to 755// simplify the logic to update AddrDieMap. The child's range will always 756// be equal or smaller than the parent's range. With this assumption, when 757// adding one range into the map, it will at most split a range into 3 764 extractDIEsIfNeeded(
false);
765if (AddrDieMap.empty())
767auto R = AddrDieMap.upper_bound(
Address);
768if (R == AddrDieMap.begin())
770// upper_bound's previous item contains Address. 774return R->second.second;
779if (
isType(Child.getTag()))
784if (Die.
getTag() != DW_TAG_variable)
790// Missing DW_AT_location is fine here. 801auto It = Expr.
begin();
805// Match exactly the main sequence used to describe global variables: 806// `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence 807// that LLVM produces for DILocalVariables and DIGlobalVariables. If, in 808// future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is 809// a good starting point) is extended to use further expressions, this code 810// needs to be updated. 812if (It->getCode() == dwarf::DW_OP_addr) {
813 LocationAddr = It->getRawOperand(0);
814 }
elseif (It->getCode() == dwarf::DW_OP_addrx) {
815uint64_t DebugAddrOffset = It->getRawOperand(0);
817 LocationAddr = Pointer->Address;
823// Read the optional 2nd operand, a DW_OP_plus_uconst. 824if (++It != Expr.
end()) {
825if (It->getCode() != dwarf::DW_OP_plus_uconst)
828 LocationAddr += It->getRawOperand(0);
830// Probe for a 3rd operand, if it exists, bail. 831if (++It != Expr.
end())
839// Get the size of the global variable. If all else fails (i.e. the global has 840// no type), then we use a size of one to still allow symbolization of the 852 extractDIEsIfNeeded(
false);
856auto RootLookup = RootsParsedForVariables.
insert(RootDie.getOffset());
857if (RootLookup.second)
860auto R = VariableDieMap.upper_bound(
Address);
861if (R == VariableDieMap.begin())
864// upper_bound's previous item contains Address. 868return R->second.second;
875// Try to look for subprogram DIEs in the DWO file. 877// First, find the subroutine that contains the given address (the leaf 882while (SubroutineDIE) {
887if (SubroutineDIE.
getTag() == DW_TAG_inlined_subroutine)
889 SubroutineDIE = SubroutineDIE.
getParent();
895if (Kind == DW_SECT_INFO)
912assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
914if (std::optional<uint32_t> ParentIdx = Die->
getParentIdx()) {
915assert(*ParentIdx < DieArray.size() &&
916"ParentIdx is out of DieArray boundaries");
934assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
936if (std::optional<uint32_t> SiblingIdx = Die->
getSiblingIdx()) {
937assert(*SiblingIdx < DieArray.size() &&
938"SiblingIdx is out of DieArray boundaries");
939return &DieArray[*SiblingIdx];
956assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
958 std::optional<uint32_t> ParentIdx = Die->
getParentIdx();
960// Die is a root die, there is no previous sibling. 963assert(*ParentIdx < DieArray.size() &&
964"ParentIdx is out of DieArray boundaries");
968if (PrevDieIdx == *ParentIdx)
969// Immediately previous node is parent, there is no previous sibling. 972while (DieArray[PrevDieIdx].getParentIdx() != *ParentIdx) {
973 PrevDieIdx = *DieArray[PrevDieIdx].getParentIdx();
975assert(PrevDieIdx < DieArray.size() &&
976"PrevDieIdx is out of DieArray boundaries");
977assert(PrevDieIdx >= *ParentIdx &&
978"PrevDieIdx is not a child of parent of Die");
981return &DieArray[PrevDieIdx];
995assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
1000// TODO: Instead of checking here for invalid die we might reject 1001// invalid dies at parsing stage(DWARFUnit::extractDIEsToVector). 1002// We do not want access out of bounds when parsing corrupted debug data. 1004if (
I >= DieArray.size())
1020assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
1025if (std::optional<uint32_t> SiblingIdx = Die->
getSiblingIdx()) {
1026assert(*SiblingIdx < DieArray.size() &&
1027"SiblingIdx is out of DieArray boundaries");
1028assert(DieArray[*SiblingIdx - 1].
getTag() == dwarf::DW_TAG_null &&
1029"Bad end of children marker");
1030return &DieArray[*SiblingIdx - 1];
1033// If SiblingIdx is set for non-root dies we could be sure that DWARF is 1034// correct and "end of children marker" must be found. For root die we do not 1035// have such a guarantee(parsing root die might be stopped if "end of children 1036// marker" is missing, SiblingIdx is always zero for root die). That is why we 1037// do not use assertion for checking for "end of children marker" for root 1040// TODO: Instead of checking here for invalid die we might reject 1041// invalid dies at parsing stage(DWARFUnit::extractDIEsToVector). 1042if (
getDIEIndex(Die) == 0 && DieArray.size() > 1 &&
1043 DieArray.back().getTag() == dwarf::DW_TAG_null) {
1044// For the unit die we might take last item from DieArray. 1048return &DieArray.back();
1058if (!AbbrevsOrError) {
1059// FIXME: We should propagate this error upwards. 1063 Abbrevs = *AbbrevsOrError;
1073 std::optional<DWARFFormValue> PC =
1074 UnitDie.
find({DW_AT_low_pc, DW_AT_entry_pc});
1083// In order to ensure that we don't read a partial record at the end of 1084// the section we validate for a multiple of the entry size. 1086// Guard against overflow. 1087if (ValidationSize >=
Size)
1088if (DA.isValidOffsetForDataOfSize((
uint32_t)
Base, ValidationSize))
1093// Look for a DWARF64-formatted contribution to the string offsets table 1094// starting at a given offset and record it in a descriptor. 1097if (!DA.isValidOffsetForDataOfSize(
Offset, 16))
1105 (void)DA.getU16(&
Offset);
// padding 1106// The encoded length includes the 2-byte version field and the 2-byte 1107// padding, so we need to subtract them out when we populate the descriptor. 1111// Look for a DWARF32-formatted contribution to the string offsets table 1112// starting at a given offset and record it in a descriptor. 1115if (!DA.isValidOffsetForDataOfSize(
Offset, 8))
1123 (void)DA.getU16(&
Offset);
// padding 1124// The encoded length includes the 2-byte version field and the 2-byte 1125// padding, so we need to subtract them out when we populate the descriptor. 1141return DescOrError.takeError();
1150return DescOrError.takeError();
1155returnDesc.validateContributionSize(DA);
1167return DescOrError.takeError();
1175auto IndexEntry = Header.getIndexEntry();
1177 IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) :
nullptr;
1181if (DA.getData().data() ==
nullptr)
1184// Look for a valid contribution at the given offset. 1187return DescOrError.takeError();
1190// Prior to DWARF v5, we derive the contribution size from the 1191// index table (in a package file). In a .dwo file it is simply 1192// the length of the string offsets section. 1196 Header.getFormat());
1197elseif (!IndexEntry && !StringOffsetSection.
Data.
empty())
1199 4, Header.getFormat());
1202auto DescOrError =
Desc.validateContributionSize(DA);
1204return DescOrError.takeError();
1215return *Off + RangeSectionBase;
1222return *Off + LocSectionBase;
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static Expected< StrOffsetsContributionDescriptor > parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset)
static Expected< StrOffsetsContributionDescriptor > parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset)
static Expected< StrOffsetsContributionDescriptor > parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, llvm::dwarf::DwarfFormat Format, uint64_t Offset)
This file contains constants used for implementing Dwarf debug support.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
A structured debug information entry.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
static bool isSupportedVersion(unsigned version)
function_ref< void(Error)> getRecoverableErrorHandler()
const DWARFUnitIndex & getTUIndex()
static Error checkAddressSizeSupported(unsigned AddressSize, std::error_code EC, char const *Fmt, const Ts &...Vals)
function_ref< void(Error)> getWarningHandler()
void setMaxVersionIfGreater(unsigned Version)
static unsigned getMaxSupportedVersion()
std::shared_ptr< DWARFContext > getDWOContext(StringRef AbsolutePath)
const DWARFUnitIndex & getCUIndex()
unit_iterator_range info_section_units()
Get units from .debug_info in this context.
const DWARFObject & getDWARFObj() const
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
std::pair< uint64_t, dwarf::DwarfFormat > getInitialLength(uint64_t *Off, Error *Err=nullptr) const
Extracts the DWARF "initial length" field, which can either be a 32-bit value smaller than 0xfffffff0...
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and applies a relocation to the result if one exists for the given offset.
Expected< const DWARFAbbreviationDeclarationSet * > getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getSiblingIdx() const
Returns index of the sibling die.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr)
DWARFAddressRangesVector getAbsoluteRanges(std::optional< object::SectionedAddress > BaseAddr) const
getAbsoluteRanges - Returns absolute address ranges defined by this range list.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Expected< DWARFAddressRangesVector > getAddressRanges() const
Get the address ranges for this DIE.
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
DWARFDie getParent() const
Get the parent of this DIE object.
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
DWARFDie getSibling() const
Get the sibling of this DIE object.
bool isSubroutineDIE() const
Returns true if DIE represents a subprogram or an inlined subroutine.
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
std::optional< uint64_t > getTypeSize(uint64_t PointerSize)
Gets the type size (in bytes) for this DIE.
DWARFDie getFirstChild() const
Get the first child of this DIE object.
dwarf::Tag getTag() const
Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
std::optional< uint64_t > getRangesBaseAttribute() const
Extract the range base attribute from this DIE as absolute section offset.
Expected< DWARFListType > findList(DWARFDataExtractor Data, uint64_t Offset) const
Look up a list based on a given offset.
static uint8_t getHeaderSize(dwarf::DwarfFormat Format)
Return the size of the table header including the length but not including the offsets.
std::optional< uint64_t > getOffsetEntry(DataExtractor Data, uint32_t Index) const
Error visitAbsoluteLocationList(uint64_t Offset, std::optional< object::SectionedAddress > BaseAddr, std::function< std::optional< object::SectionedAddress >(uint32_t)> LookupAddr, function_ref< bool(Expected< DWARFLocationExpression >)> Callback) const
virtual const DWARFSection & getLoclistsSection() const
virtual const DWARFSection & getLocDWOSection() const
virtual const DWARFSection & getRnglistsDWOSection() const
virtual const DWARFSection & getLocSection() const
virtual const DWARFSection & getRnglistsSection() const
virtual const DWARFSection & getLoclistsDWOSection() const
Base class describing the header of any kind of "unit." Some information is specific to certain unit ...
Error extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, uint64_t *offset_ptr, DWARFSectionKind SectionKind)
Parse a unit header from debug_info starting at offset_ptr.
Error applyIndexEntry(const DWARFUnitIndex::Entry *Entry)
uint64_t getLength() const
uint16_t getVersion() const
uint8_t getAddressByteSize() const
uint64_t getNextUnitOffset() const
uint8_t getUnitLengthFieldByteSize() const
const SectionContribution * getContribution(DWARFSectionKind Sec) const
Describe a collection of units.
DWARFUnit * addUnit(std::unique_ptr< DWARFUnit > Unit)
Add an existing DWARFUnit to this UnitVector.
unsigned getNumInfoUnits() const
Returns number of units from all .debug_info[.dwo] sections.
void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind)
Read units from a .debug_info or .debug_types section.
DWARFUnit * getUnitForOffset(uint64_t Offset) const
void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, DWARFSectionKind SectionKind, bool Lazy=false)
Read units from a .debug_info.dwo or .debug_types.dwo section.
DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E)
const DWARFDebugInfoEntry * getDebugInfoEntry(unsigned Index) const
Return DWARFDebugInfoEntry for the specified index Index.
const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const
std::optional< uint64_t > getDWOId()
uint32_t getHeaderSize() const
Size in bytes of the parsed unit header.
DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die)
Expected< std::optional< StrOffsetsContributionDescriptor > > determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form.
const DWARFLocationTable & getLocationTable()
const DWARFDebugInfoEntry * getParentEntry(const DWARFDebugInfoEntry *Die) const
DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die)
DWARFDataExtractor getDebugInfoExtractor() const
DWARFDie getSibling(const DWARFDebugInfoEntry *Die)
std::optional< uint64_t > getRnglistOffset(uint32_t Index)
Return a rangelist's offset based on an index.
Error tryExtractDIEsIfNeeded(bool CUDieOnly)
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint8_t getAddressByteSize() const
DWARFDie getVariableForAddress(uint64_t Address)
Returns variable DIE for the address provided.
void setRangesSection(const DWARFSection *RS, uint64_t Base)
uint8_t getDwarfStringOffsetsByteSize() const
const DWARFAbbreviationDeclarationSet * getAbbreviations() const
DWARFDie getParent(const DWARFDebugInfoEntry *Die)
std::optional< uint64_t > getLoclistOffset(uint32_t Index)
const char * getCompilationDir()
uint64_t getStringOffsetsBase() const
dwarf::DwarfFormat getFormat() const
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)
Expected< std::optional< StrOffsetsContributionDescriptor > > determineStringOffsetsTableContribution(DWARFDataExtractor &DA)
Find the unit's contribution to the string offsets table and determine its length and form.
uint64_t getAbbreviationsOffset() const
uint16_t getVersion() const
void getInlinedChainForAddress(uint64_t Address, SmallVectorImpl< DWARFDie > &InlinedChain)
getInlinedChainForAddress - fetches inlined chain for a given address.
Error extractRangeList(uint64_t RangeListOffset, DWARFDebugRangeList &RangeList) const
Extract the range list referenced by this compile unit from the .debug_ranges section.
Expected< uint64_t > getStringOffsetSectionItem(uint32_t Index) const
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
Return the index of a Die entry inside the unit's DIE vector.
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
Expected< DWARFAddressRangesVector > findRnglistFromOffset(uint64_t Offset)
Return a vector of address ranges resulting from a (possibly encoded) range list starting at a given ...
bool isLittleEndian() const
const DWARFDebugInfoEntry * getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const
const DWARFDebugInfoEntry * getLastChildEntry(const DWARFDebugInfoEntry *Die) const
void updateVariableDieMap(DWARFDie Die)
Recursively update address to variable Die map.
DWARFDie getSubroutineForAddress(uint64_t Address)
Returns subprogram DIE with address range encompassing the provided address.
const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) 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...
uint64_t getNextUnitOffset() const
std::optional< object::SectionedAddress > getBaseAddress()
Expected< DWARFAddressRangesVector > collectAddressRanges()
std::optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
uint64_t getOffset() const
DWARFDie getLastChild(const DWARFDebugInfoEntry *Die)
void updateAddressDieMap(DWARFDie Die)
Recursively update address to Die map.
uint64_t getUnsigned(uint64_t *offset_ptr, uint32_t byte_size, Error *Err=nullptr) const
Extract an unsigned integer of size byte_size from *offset_ptr.
size_t size() const
Return the number of bytes in the underlying buffer.
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
uint64_t getU64(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint64_t value from *offset_ptr.
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
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.
SectionKind - This is a simple POD value that classifies the properties of a section.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::pair< iterator, bool > insert(const ValueT &V)
unsigned getTag(StringRef TagString)
@ C
The default llvm calling convention, compatible with C.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< object::SectionedAddress > toSectionedAddress(const std::optional< DWARFFormValue > &V)
UnitType
Constants for unit types in DWARF v5.
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
@ DW_LENGTH_lo_reserved
Special values for an initial length field.
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
const DWARFUnitIndex & getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind)
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
const char * toString(DWARFSectionKind Kind)
void consumeError(Error Err)
Consume a Error without doing anything.
Description of the encoding of one expression Op.
Represents a single DWARF expression, whose value is location-dependent.
Represents base address of the CU.
Expected< StrOffsetsContributionDescriptor > validateContributionSize(DWARFDataExtractor &DA)
Determine whether a contribution to the string offsets table is consistent with the relevant section ...
uint64_t Size
The contribution size not including the header.
uint8_t getDwarfOffsetByteSize() const
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.