From b4ea5a3b36076116e4a143dc053950feef839458 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 19 Sep 2017 18:36:11 +0000 Subject: [PATCH] dwarfdump/symbolizer: Avoid loading unneeded CUs from a DWP When symbolizing large binaries, parsing every CU in a DWP file is a significant performance penalty. Instead, use the index to only load the CUs that are needed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313659 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/DWARF/DWARFUnit.h | 71 ++++++++++++++++++++---- lib/DebugInfo/DWARF/DWARFContext.cpp | 5 +- lib/DebugInfo/DWARF/DWARFUnit.cpp | 8 +-- lib/DebugInfo/DWARF/DWARFUnitIndex.cpp | 7 ++- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index ebe8cc66d4f..0df5c16e4a2 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -47,10 +47,11 @@ public: /// Returns the Unit that contains the given section offset in the /// same section this Unit originated from. virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0; void parse(DWARFContext &C, const DWARFSection &Section); void parseDWO(DWARFContext &C, const DWARFSection &DWOSection, - DWARFUnitIndex *Index = nullptr); + bool Lazy = false); protected: ~DWARFUnitSectionBase() = default; @@ -59,7 +60,7 @@ protected: const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, - bool isLittleEndian, bool isDWO) = 0; + bool isLittleEndian, bool isDWO, bool Lazy) = 0; }; const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, @@ -70,6 +71,7 @@ template class DWARFUnitSection final : public SmallVector, 1>, public DWARFUnitSectionBase { bool Parsed = false; + std::function(uint32_t)> Parser; public: using UnitVector = SmallVectorImpl>; @@ -82,29 +84,76 @@ public: [](uint32_t LHS, const std::unique_ptr &RHS) { return LHS < RHS->getNextUnitOffset(); }); - if (CU != this->end()) + if (CU != this->end() && (*CU)->getOffset() <= Offset) return CU->get(); return nullptr; } + UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override { + const auto *CUOff = E.getOffset(DW_SECT_INFO); + if (!CUOff) + return nullptr; + + auto Offset = CUOff->Offset; + + auto *CU = std::upper_bound( + this->begin(), this->end(), CUOff->Offset, + [](uint32_t LHS, const std::unique_ptr &RHS) { + return LHS < RHS->getNextUnitOffset(); + }); + if (CU != this->end() && (*CU)->getOffset() <= Offset) + return CU->get(); + + if (!Parser) + return nullptr; + + auto U = Parser(Offset); + if (!U) + U = nullptr; + + auto *NewCU = U.get(); + this->insert(CU, std::move(U)); + return NewCU; + } private: void parseImpl(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, - const DWARFSection &LS, bool LE, bool IsDWO) override { + const DWARFSection &LS, bool LE, bool IsDWO, + bool Lazy) override { if (Parsed) return; - const auto &Index = getDWARFUnitIndex(Context, UnitType::Section); DataExtractor Data(Section.Data, LE, 0); + if (!Parser) { + const DWARFUnitIndex *Index = nullptr; + if (IsDWO) + Index = &getDWARFUnitIndex(Context, UnitType::Section); + Parser = [=, &Context, &Section, &SOS, + &LS](uint32_t Offset) -> std::unique_ptr { + if (!Data.isValidOffset(Offset)) + return nullptr; + auto U = llvm::make_unique( + Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this, + Index ? Index->getFromOffset(Offset) : nullptr); + if (!U->extract(Data, &Offset)) + return nullptr; + return U; + }; + } + if (Lazy) + return; + auto I = this->begin(); uint32_t Offset = 0; while (Data.isValidOffset(Offset)) { - auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, - AOS, LS, LE, IsDWO, *this, - Index.getFromOffset(Offset)); - if (!U->extract(Data, &Offset)) + if (I != this->end() && (*I)->getOffset() == Offset) { + ++I; + continue; + } + auto U = Parser(Offset); + if (!U) break; - this->push_back(std::move(U)); - Offset = this->back()->getNextUnitOffset(); + Offset = U->getNextUnitOffset(); + I = std::next(this->insert(I, std::move(U))); } Parsed = true; } diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 90df9f4e787..0e28954f5c1 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -464,12 +464,11 @@ void DWARFContext::dump( } DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { - parseDWOCompileUnits(); + DWOCUs.parseDWO(*this, DObj->getInfoDWOSection(), true); if (const auto &CUI = getCUIndex()) { if (const auto *R = CUI.getFromHash(Hash)) - if (auto CUOff = R->getOffset(DW_SECT_INFO)) - return DWOCUs.getUnitForOffset(CUOff->Offset); + return DWOCUs.getUnitForIndexEntry(*R); return nullptr; } diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 4467b4ac309..86451faa79d 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -33,17 +33,17 @@ void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { const DWARFObject &D = C.getDWARFObj(); parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(), D.getStringSection(), D.getStringOffsetSection(), - &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false); + &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false, + false); } void DWARFUnitSectionBase::parseDWO(DWARFContext &C, - const DWARFSection &DWOSection, - DWARFUnitIndex *Index) { + const DWARFSection &DWOSection, bool Lazy) { const DWARFObject &D = C.getDWARFObj(); parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), D.getStringDWOSection(), D.getStringOffsetDWOSection(), &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), - true); + true, Lazy); } DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, diff --git a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 6e8cbcad491..17f17572a30 100644 --- a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -165,9 +165,12 @@ DWARFUnitIndex::Entry::getOffset() const { const DWARFUnitIndex::Entry * DWARFUnitIndex::getFromOffset(uint32_t Offset) const { for (uint32_t i = 0; i != Header.NumBuckets; ++i) - if (const auto &Contribs = Rows[i].Contributions) - if (Contribs[InfoColumn].Offset == Offset) + if (const auto &Contribs = Rows[i].Contributions) { + const auto &InfoContrib = Contribs[InfoColumn]; + if (InfoContrib.Offset <= Offset && + Offset < (InfoContrib.Offset + InfoContrib.Length)) return &Rows[i]; + } return nullptr; } -- 2.49.0