void DWARFUnitVector::addUnitsImpl( DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, const DWARFDebugAbbrev *DA, const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, bool Lazy, DWARFSectionKind SectionKind) { DWARFDataExtractor Data(Obj, Section, LE, 0); // Lazy initialization of Parser, now that we have all section info. if (!Parser) { Parser = [=, &Context, &Obj, &Section, &SOS, &LS]( uint32_t Offset, DWARFSectionKind SectionKind, const DWARFSection *CurSection) -> std::unique_ptr<DWARFUnit> { const DWARFSection &InfoSection = CurSection ? *CurSection : Section; DWARFDataExtractor Data(Obj, InfoSection, LE, 0); if (!Data.isValidOffset(Offset)) return nullptr; const DWARFUnitIndex *Index = nullptr; if (IsDWO) Index = &getDWARFUnitIndex(Context, SectionKind); DWARFUnitHeader Header; if (!Header.extract(Context, Data, &Offset, SectionKind, Index)) return nullptr; std::unique_ptr<DWARFUnit> U; if (Header.isTypeUnit()) U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, RS, LocSection, SS, SOS, AOS, LS, LE, IsDWO, *this); else U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, DA, RS, LocSection, SS, SOS, AOS, LS, LE, IsDWO, *this); return U; }; } if (Lazy) return; // Find a reasonable insertion point within the vector. We skip over // (a) units from a different section, (b) units from the same section // but with lower offset-within-section. This keeps units in order // within a section, although not necessarily within the object file, // even if we do lazy parsing. auto I = this->begin(); uint32_t Offset = 0; while (Data.isValidOffset(Offset)) { if (I != this->end() && (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { ++I; continue; } auto U = Parser(Offset, SectionKind, &Section); // If parsing failed, we're done with this section. if (!U) break; Offset = U->getNextUnitOffset(); I = std::next(this->insert(I, std::move(U))); } }
unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, DWARFSectionKind SectionKind) { const DWARFObject &DObj = DCtx.getDWARFObj(); DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0); unsigned NumDebugInfoErrors = 0; uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0; uint8_t UnitType = 0; bool isUnitDWARF64 = false; bool isHeaderChainValid = true; bool hasDIE = DebugInfoData.isValidOffset(Offset); DWARFUnitVector UnitVector{}; while (hasDIE) { OffsetStart = Offset; if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType, isUnitDWARF64)) { isHeaderChainValid = false; if (isUnitDWARF64) break; } else { DWARFUnitHeader Header; Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind); std::unique_ptr<DWARFUnit> Unit; switch (UnitType) { case dwarf::DW_UT_type: case dwarf::DW_UT_split_type: { Unit.reset(new DWARFTypeUnit( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), DObj.getStringSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, UnitVector)); break; } case dwarf::DW_UT_skeleton: case dwarf::DW_UT_split_compile: case dwarf::DW_UT_compile: case dwarf::DW_UT_partial: // UnitType = 0 means that we are // verifying a compile unit in DWARF v4. case 0: { Unit.reset(new DWARFCompileUnit( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), DObj.getStringSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, UnitVector)); break; } default: { llvm_unreachable("Invalid UnitType."); } } NumDebugInfoErrors += verifyUnitContents(*Unit, UnitType); } hasDIE = DebugInfoData.isValidOffset(Offset); ++UnitIdx; } if (UnitIdx == 0 && !hasDIE) { warn() << "Section is empty.\n"; isHeaderChainValid = true; } if (!isHeaderChainValid) ++NumDebugInfoErrors; NumDebugInfoErrors += verifyDebugInfoReferences(); return NumDebugInfoErrors; }