summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp110
1 files changed, 75 insertions, 35 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 8493950a29b2..f17dacfce665 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -192,17 +192,18 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
Optional<object::SectionedAddress>
DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
- if (IsDWO) {
+ if (!AddrOffsetSectionBase) {
auto R = Context.info_section_units();
// Surprising if a DWO file has more than one skeleton unit in it - this
// probably shouldn't be valid, but if a use case is found, here's where to
// support it (probably have to linearly search for the matching skeleton CU
// here)
- if (hasSingleElement(R))
+ if (IsDWO && hasSingleElement(R))
return (*R.begin())->getAddrOffsetSectionItem(Index);
- }
- if (!AddrOffsetSectionBase)
+
return None;
+ }
+
uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize();
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
return None;
@@ -258,26 +259,73 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
} else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
DWOId = debug_info.getU64(offset_ptr, &Err);
- if (errorToBool(std::move(Err)))
+ if (Err) {
+ Context.getWarningHandler()(joinErrors(
+ createStringError(
+ errc::invalid_argument,
+ "DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset),
+ std::move(Err)));
return false;
+ }
// Header fields all parsed, capture the size of this unit header.
assert(*offset_ptr - Offset <= 255 && "unexpected header size");
Size = uint8_t(*offset_ptr - Offset);
+ uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength();
+
+ if (!debug_info.isValidOffset(getNextUnitOffset() - 1)) {
+ Context.getWarningHandler()(
+ createStringError(errc::invalid_argument,
+ "DWARF unit from offset 0x%8.8" PRIx64 " incl. "
+ "to offset 0x%8.8" PRIx64 " excl. "
+ "extends past section size 0x%8.8zx",
+ Offset, NextCUOffset, debug_info.size()));
+ return false;
+ }
+
+ if (!DWARFContext::isSupportedVersion(getVersion())) {
+ Context.getWarningHandler()(createStringError(
+ errc::invalid_argument,
+ "DWARF unit at offset 0x%8.8" PRIx64 " "
+ "has unsupported version %" PRIu16 ", supported are 2-%u",
+ Offset, getVersion(), DWARFContext::getMaxSupportedVersion()));
+ return false;
+ }
// Type offset is unit-relative; should be after the header and before
// the end of the current unit.
- bool TypeOffsetOK =
- !isTypeUnit()
- ? true
- : TypeOffset >= Size &&
- TypeOffset < getLength() + getUnitLengthFieldByteSize();
- bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
- bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
- bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize());
+ if (isTypeUnit() && TypeOffset < Size) {
+ Context.getWarningHandler()(
+ createStringError(errc::invalid_argument,
+ "DWARF type unit at offset "
+ "0x%8.8" PRIx64 " "
+ "has its relocated type_offset 0x%8.8" PRIx64 " "
+ "pointing inside the header",
+ Offset, Offset + TypeOffset));
+ return false;
+ }
+ if (isTypeUnit() &&
+ TypeOffset >= getUnitLengthFieldByteSize() + getLength()) {
+ Context.getWarningHandler()(createStringError(
+ errc::invalid_argument,
+ "DWARF type unit from offset 0x%8.8" PRIx64 " incl. "
+ "to offset 0x%8.8" PRIx64 " excl. has its "
+ "relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end",
+ Offset, NextCUOffset, Offset + TypeOffset));
+ return false;
+ }
- if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
+ if (!DWARFContext::isAddressSizeSupported(getAddressByteSize())) {
+ SmallVector<std::string, 3> Sizes;
+ for (auto Size : DWARFContext::getSupportedAddressSizes())
+ Sizes.push_back(std::to_string(Size));
+ Context.getWarningHandler()(createStringError(
+ errc::invalid_argument,
+ "DWARF unit at offset 0x%8.8" PRIx64 " "
+ "has unsupported address size %" PRIu8 ", supported are %s",
+ Offset, getAddressByteSize(), llvm::join(Sizes, ", ").c_str()));
return false;
+ }
// Keep track of the highest DWARF version we encounter across all units.
Context.setMaxVersionIfGreater(getVersion());
@@ -340,6 +388,7 @@ void DWARFUnit::clear() {
RangeSectionBase = 0;
LocSectionBase = 0;
AddrOffsetSectionBase = None;
+ SU = nullptr;
clearDIEs(false);
DWO.reset();
}
@@ -360,6 +409,8 @@ void DWARFUnit::extractDIEsToVector(
uint64_t NextCUOffset = getNextUnitOffset();
DWARFDebugInfoEntry DIE;
DWARFDataExtractor DebugInfoData = getDebugInfoExtractor();
+ // The end offset has been already checked by DWARFUnitHeader::extract.
+ assert(DebugInfoData.isValidOffset(NextCUOffset - 1));
uint32_t Depth = 0;
bool IsCUDie = true;
@@ -384,6 +435,8 @@ void DWARFUnit::extractDIEsToVector(
// Normal DIE
if (AbbrDecl->hasChildren())
++Depth;
+ else if (Depth == 0)
+ break; // This unit has a single DIE with no children.
} else {
// NULL DIE.
if (Depth > 0)
@@ -392,17 +445,6 @@ void DWARFUnit::extractDIEsToVector(
break; // We are done with this compile unit!
}
}
-
- // Give a little bit of info if we encounter corrupt DWARF (our offset
- // should always terminate at or before the start of the next compilation
- // unit header).
- if (DIEOffset > NextCUOffset)
- Context.getWarningHandler()(
- createStringError(errc::invalid_argument,
- "DWARF compile unit extends beyond its "
- "bounds cu 0x%8.8" PRIx64 " "
- "at 0x%8.8" PRIx64 "\n",
- getOffset(), DIEOffset));
}
void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
@@ -545,13 +587,11 @@ bool DWARFUnit::parseDWO() {
if (!DWOCU)
return false;
DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
+ DWO->setSkeletonUnit(this);
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
if (AddrOffsetSectionBase)
DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
- if (getVersion() >= 5) {
- DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(),
- DWARFListTableHeader::getHeaderSize(getFormat()));
- } else {
+ if (getVersion() == 4) {
auto DWORangesBase = UnitDie.getRangesBaseAttribute();
DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
}
@@ -688,15 +728,15 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address,
DWARFDie SubroutineDIE =
(DWO ? *DWO : *this).getSubroutineForAddress(Address);
- if (!SubroutineDIE)
- return;
-
- while (!SubroutineDIE.isSubprogramDIE()) {
+ while (SubroutineDIE) {
+ if (SubroutineDIE.isSubprogramDIE()) {
+ InlinedChain.push_back(SubroutineDIE);
+ return;
+ }
if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
InlinedChain.push_back(SubroutineDIE);
SubroutineDIE = SubroutineDIE.getParent();
}
- InlinedChain.push_back(SubroutineDIE);
}
const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
@@ -793,7 +833,7 @@ DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
if (!Abbrevs)
- Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset());
+ Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset());
return Abbrevs;
}