aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp208
1 files changed, 136 insertions, 72 deletions
diff --git a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 74667fcb92bc..c199e0118a6f 100644
--- a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -134,11 +134,11 @@ void DWARFUnitVector::addUnitsImpl(
}
DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) {
- auto I = std::upper_bound(begin(), end(), Unit,
- [](const std::unique_ptr<DWARFUnit> &LHS,
- const std::unique_ptr<DWARFUnit> &RHS) {
- return LHS->getOffset() < RHS->getOffset();
- });
+ auto I = llvm::upper_bound(*this, Unit,
+ [](const std::unique_ptr<DWARFUnit> &LHS,
+ const std::unique_ptr<DWARFUnit> &RHS) {
+ return LHS->getOffset() < RHS->getOffset();
+ });
return this->insert(I, std::move(Unit))->get();
}
@@ -160,11 +160,11 @@ DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
if (!CUOff)
return nullptr;
- auto Offset = CUOff->Offset;
+ uint64_t Offset = CUOff->getOffset();
auto end = begin() + getNumInfoUnits();
auto *CU =
- std::upper_bound(begin(), end, CUOff->Offset,
+ std::upper_bound(begin(), end, CUOff->getOffset(),
[](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
return LHS < RHS->getNextUnitOffset();
});
@@ -192,7 +192,7 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
bool IsDWO, const DWARFUnitVector &UnitVector)
: Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
RangeSection(RS), LineSection(LS), StringSection(SS),
- StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE),
+ StringOffsetSection(SOS), AddrOffsetSection(AOS), IsLittleEndian(LE),
IsDWO(IsDWO), UnitVector(UnitVector) {
clear();
}
@@ -200,11 +200,11 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
DWARFUnit::~DWARFUnit() = default;
DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
- return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian,
+ return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, IsLittleEndian,
getAddressByteSize());
}
-Optional<object::SectionedAddress>
+std::optional<object::SectionedAddress>
DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
if (!AddrOffsetSectionBase) {
auto R = Context.info_section_units();
@@ -215,14 +215,14 @@ DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
if (IsDWO && hasSingleElement(R))
return (*R.begin())->getAddrOffsetSectionItem(Index);
- return None;
+ return std::nullopt;
}
uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize();
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
- return None;
+ return std::nullopt;
DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
- isLittleEndian, getAddressByteSize());
+ IsLittleEndian, getAddressByteSize());
uint64_t Section;
uint64_t Address = DA.getRelocatedAddress(&Offset, &Section);
return {{Address, Section}};
@@ -240,7 +240,7 @@ Expected<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
", which is too large",
inconvertibleErrorCode());
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
- isLittleEndian, 0);
+ IsLittleEndian, 0);
return DA.getRelocatedValue(ItemSize, &Offset);
}
@@ -353,12 +353,12 @@ bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) {
return false;
auto *UnitContrib = IndexEntry->getContribution();
if (!UnitContrib ||
- UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize()))
+ UnitContrib->getLength() != (getLength() + getUnitLengthFieldByteSize()))
return false;
auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
if (!AbbrEntry)
return false;
- AbbrOffset = AbbrEntry->Offset;
+ AbbrOffset = AbbrEntry->getOffset();
return true;
}
@@ -367,7 +367,7 @@ Error DWARFUnit::extractRangeList(uint64_t RangeListOffset,
// Require that compile unit is extracted.
assert(!DieArray.empty());
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, getAddressByteSize());
+ IsLittleEndian, getAddressByteSize());
uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
return RangeList.extract(RangesData, &ActualRangeListOffset);
}
@@ -377,7 +377,7 @@ void DWARFUnit::clear() {
BaseAddr.reset();
RangeSectionBase = 0;
LocSectionBase = 0;
- AddrOffsetSectionBase = None;
+ AddrOffsetSectionBase = std::nullopt;
SU = nullptr;
clearDIEs(false);
AddrDieMap.clear();
@@ -499,10 +499,11 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
return Error::success();
DWARFDie UnitDie(this, &DieArray[0]);
- if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
+ if (std::optional<uint64_t> DWOId =
+ toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
Header.setDWOId(*DWOId);
if (!IsDWO) {
- assert(AddrOffsetSectionBase == None);
+ assert(AddrOffsetSectionBase == std::nullopt);
assert(RangeSectionBase == 0);
assert(LocSectionBase == 0);
AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base));
@@ -521,7 +522,7 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
// In both cases we need to determine the format of the contribution,
// which may differ from the unit's format.
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
- isLittleEndian, 0);
+ IsLittleEndian, 0);
if (IsDWO || getVersion() >= 5) {
auto StringOffsetOrError =
IsDWO ? determineStringOffsetsTableContributionDWO(DA)
@@ -543,7 +544,7 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
uint64_t ContributionBaseOffset = 0;
if (auto *IndexEntry = Header.getIndexEntry())
if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
- ContributionBaseOffset = Contrib->Offset;
+ ContributionBaseOffset = Contrib->getOffset();
setRangesSection(
&Context.getDWARFObj().getRnglistsDWOSection(),
ContributionBaseOffset +
@@ -564,9 +565,9 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
if (auto *IndexEntry = Header.getIndexEntry())
if (const auto *C = IndexEntry->getContribution(
Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
- Data = Data.substr(C->Offset, C->Length);
+ Data = Data.substr(C->getOffset(), C->getLength());
- DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize());
+ DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize());
LocTable =
std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat());
@@ -574,12 +575,12 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
LocTable = std::make_unique<DWARFDebugLoclists>(
DWARFDataExtractor(Context.getDWARFObj(),
Context.getDWARFObj().getLoclistsSection(),
- isLittleEndian, getAddressByteSize()),
+ IsLittleEndian, getAddressByteSize()),
getVersion());
} else {
LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor(
Context.getDWARFObj(), Context.getDWARFObj().getLocSection(),
- isLittleEndian, getAddressByteSize()));
+ IsLittleEndian, getAddressByteSize()));
}
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
@@ -587,10 +588,10 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
return Error::success();
}
-bool DWARFUnit::parseDWO() {
+bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
if (IsDWO)
return false;
- if (DWO.get())
+ if (DWO)
return false;
DWARFDie UnitDie = getUnitDIE();
if (!UnitDie)
@@ -611,8 +612,17 @@ bool DWARFUnit::parseDWO() {
if (!DWOId)
return false;
auto DWOContext = Context.getDWOContext(AbsolutePath);
- if (!DWOContext)
- return false;
+ if (!DWOContext) {
+ // Use the alternative location to get the DWARF context for the DWO object.
+ if (DWOAlternativeLocation.empty())
+ return false;
+ // If the alternative context does not correspond to the original DWO object
+ // (different hashes), the below 'getDWOCompileUnitForHash' call will catch
+ // the issue, with a returned null context.
+ DWOContext = Context.getDWOContext(DWOAlternativeLocation);
+ if (!DWOContext)
+ return false;
+ }
DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId);
if (!DWOCU)
@@ -650,7 +660,7 @@ DWARFUnit::findRnglistFromOffset(uint64_t Offset) {
return RangeList.getAbsoluteRanges(getBaseAddress());
}
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, Header.getAddressByteSize());
+ IsLittleEndian, Header.getAddressByteSize());
DWARFDebugRnglistTable RnglistTable;
auto RangeListOrError = RnglistTable.findList(RangesData, Offset);
if (RangeListOrError)
@@ -819,7 +829,7 @@ void DWARFUnit::updateVariableDieMap(DWARFDie Die) {
// exact address.
uint64_t GVSize = 1;
if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
- if (Optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize()))
+ if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize()))
GVSize = *Size;
if (Address != UINT64_MAX)
@@ -877,39 +887,66 @@ const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
}
DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
+ if (const DWARFDebugInfoEntry *Entry = getParentEntry(Die))
+ return DWARFDie(this, Entry);
+
+ return DWARFDie();
+}
+
+const DWARFDebugInfoEntry *
+DWARFUnit::getParentEntry(const DWARFDebugInfoEntry *Die) const {
if (!Die)
- return DWARFDie();
+ return nullptr;
+ assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
- if (Optional<uint32_t> ParentIdx = Die->getParentIdx()) {
+ if (std::optional<uint32_t> ParentIdx = Die->getParentIdx()) {
assert(*ParentIdx < DieArray.size() &&
"ParentIdx is out of DieArray boundaries");
- return DWARFDie(this, &DieArray[*ParentIdx]);
+ return getDebugInfoEntry(*ParentIdx);
}
- return DWARFDie();
+ return nullptr;
}
DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
+ if (const DWARFDebugInfoEntry *Sibling = getSiblingEntry(Die))
+ return DWARFDie(this, Sibling);
+
+ return DWARFDie();
+}
+
+const DWARFDebugInfoEntry *
+DWARFUnit::getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
if (!Die)
- return DWARFDie();
+ return nullptr;
+ assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
- if (Optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
+ if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
assert(*SiblingIdx < DieArray.size() &&
"SiblingIdx is out of DieArray boundaries");
- return DWARFDie(this, &DieArray[*SiblingIdx]);
+ return &DieArray[*SiblingIdx];
}
- return DWARFDie();
+ return nullptr;
}
DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
+ if (const DWARFDebugInfoEntry *Sibling = getPreviousSiblingEntry(Die))
+ return DWARFDie(this, Sibling);
+
+ return DWARFDie();
+}
+
+const DWARFDebugInfoEntry *
+DWARFUnit::getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const {
if (!Die)
- return DWARFDie();
+ return nullptr;
+ assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
- Optional<uint32_t> ParentIdx = Die->getParentIdx();
+ std::optional<uint32_t> ParentIdx = Die->getParentIdx();
if (!ParentIdx)
// Die is a root die, there is no previous sibling.
- return DWARFDie();
+ return nullptr;
assert(*ParentIdx < DieArray.size() &&
"ParentIdx is out of DieArray boundaries");
@@ -918,7 +955,7 @@ DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
uint32_t PrevDieIdx = getDIEIndex(Die) - 1;
if (PrevDieIdx == *ParentIdx)
// Immediately previous node is parent, there is no previous sibling.
- return DWARFDie();
+ return nullptr;
while (DieArray[PrevDieIdx].getParentIdx() != *ParentIdx) {
PrevDieIdx = *DieArray[PrevDieIdx].getParentIdx();
@@ -929,32 +966,56 @@ DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
"PrevDieIdx is not a child of parent of Die");
}
- return DWARFDie(this, &DieArray[PrevDieIdx]);
+ return &DieArray[PrevDieIdx];
}
DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) {
+ if (const DWARFDebugInfoEntry *Child = getFirstChildEntry(Die))
+ return DWARFDie(this, Child);
+
+ return DWARFDie();
+}
+
+const DWARFDebugInfoEntry *
+DWARFUnit::getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
+ if (!Die)
+ return nullptr;
+ assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
+
if (!Die->hasChildren())
- return DWARFDie();
+ return nullptr;
// TODO: Instead of checking here for invalid die we might reject
// invalid dies at parsing stage(DWARFUnit::extractDIEsToVector).
// We do not want access out of bounds when parsing corrupted debug data.
size_t I = getDIEIndex(Die) + 1;
if (I >= DieArray.size())
- return DWARFDie();
- return DWARFDie(this, &DieArray[I]);
+ return nullptr;
+ return &DieArray[I];
}
DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
+ if (const DWARFDebugInfoEntry *Child = getLastChildEntry(Die))
+ return DWARFDie(this, Child);
+
+ return DWARFDie();
+}
+
+const DWARFDebugInfoEntry *
+DWARFUnit::getLastChildEntry(const DWARFDebugInfoEntry *Die) const {
+ if (!Die)
+ return nullptr;
+ assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
+
if (!Die->hasChildren())
- return DWARFDie();
+ return nullptr;
- if (Optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
+ if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
assert(*SiblingIdx < DieArray.size() &&
"SiblingIdx is out of DieArray boundaries");
assert(DieArray[*SiblingIdx - 1].getTag() == dwarf::DW_TAG_null &&
"Bad end of children marker");
- return DWARFDie(this, &DieArray[*SiblingIdx - 1]);
+ return &DieArray[*SiblingIdx - 1];
}
// If SiblingIdx is set for non-root dies we could be sure that DWARF is
@@ -969,11 +1030,13 @@ DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
if (getDIEIndex(Die) == 0 && DieArray.size() > 1 &&
DieArray.back().getTag() == dwarf::DW_TAG_null) {
// For the unit die we might take last item from DieArray.
- assert(getDIEIndex(Die) == getDIEIndex(getUnitDIE()) && "Bad unit die");
- return DWARFDie(this, &DieArray.back());
+ assert(getDIEIndex(Die) ==
+ getDIEIndex(const_cast<DWARFUnit *>(this)->getUnitDIE()) &&
+ "Bad unit die");
+ return &DieArray.back();
}
- return DWARFDie();
+ return nullptr;
}
const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
@@ -982,12 +1045,13 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
return Abbrevs;
}
-llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
+std::optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
if (BaseAddr)
return BaseAddr;
DWARFDie UnitDie = getUnitDIE();
- Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
+ std::optional<DWARFFormValue> PC =
+ UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
BaseAddr = toSectionedAddress(PC);
return BaseAddr;
}
@@ -1071,12 +1135,12 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
return Desc.validateContributionSize(DA);
}
-Expected<Optional<StrOffsetsContributionDescriptor>>
+Expected<std::optional<StrOffsetsContributionDescriptor>>
DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
assert(!IsDWO);
auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base));
if (!OptOffset)
- return None;
+ return std::nullopt;
auto DescOrError =
parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset);
if (!DescOrError)
@@ -1084,18 +1148,18 @@ DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
return *DescOrError;
}
-Expected<Optional<StrOffsetsContributionDescriptor>>
-DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
+Expected<std::optional<StrOffsetsContributionDescriptor>>
+DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA) {
assert(IsDWO);
uint64_t Offset = 0;
auto IndexEntry = Header.getIndexEntry();
const auto *C =
IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr;
if (C)
- Offset = C->Offset;
+ Offset = C->getOffset();
if (getVersion() >= 5) {
if (DA.getData().data() == nullptr)
- return None;
+ return std::nullopt;
Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
// Look for a valid contribution at the given offset.
auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
@@ -1108,33 +1172,33 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
// the length of the string offsets section.
StrOffsetsContributionDescriptor Desc;
if (C)
- Desc = StrOffsetsContributionDescriptor(C->Offset, C->Length, 4,
+ Desc = StrOffsetsContributionDescriptor(C->getOffset(), C->getLength(), 4,
Header.getFormat());
else if (!IndexEntry && !StringOffsetSection.Data.empty())
Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(),
4, Header.getFormat());
else
- return None;
+ return std::nullopt;
auto DescOrError = Desc.validateContributionSize(DA);
if (!DescOrError)
return DescOrError.takeError();
return *DescOrError;
}
-Optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) {
- DataExtractor RangesData(RangeSection->Data, isLittleEndian,
+std::optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) {
+ DataExtractor RangesData(RangeSection->Data, IsLittleEndian,
getAddressByteSize());
DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, 0);
- if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
+ IsLittleEndian, 0);
+ if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
RangesData, RangeSectionBase, getFormat(), Index))
return *Off + RangeSectionBase;
- return None;
+ return std::nullopt;
}
-Optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) {
- if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
+std::optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) {
+ if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
LocTable->getData(), LocSectionBase, getFormat(), Index))
return *Off + LocSectionBase;
- return None;
+ return std::nullopt;
}