[llvm] r313659 - dwarfdump/symbolizer: Avoid loading unneeded CUs from a DWP

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 19 11:36:11 PDT 2017


Author: dblaikie
Date: Tue Sep 19 11:36:11 2017
New Revision: 313659

URL: http://llvm.org/viewvc/llvm-project?rev=313659&view=rev
Log:
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.

Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=313659&r1=313658&r2=313659&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h Tue Sep 19 11:36:11 2017
@@ -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<typename UnitType>
 class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
                                public DWARFUnitSectionBase {
   bool Parsed = false;
+  std::function<std::unique_ptr<UnitType>(uint32_t)> Parser;
 
 public:
   using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>;
@@ -82,29 +84,76 @@ public:
         [](uint32_t LHS, const std::unique_ptr<UnitType> &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<UnitType> &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<UnitType> {
+        if (!Data.isValidOffset(Offset))
+          return nullptr;
+        auto U = llvm::make_unique<UnitType>(
+            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<UnitType>(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;
   }

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=313659&r1=313658&r2=313659&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Tue Sep 19 11:36:11 2017
@@ -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;
   }
 

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp?rev=313659&r1=313658&r2=313659&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp Tue Sep 19 11:36:11 2017
@@ -33,17 +33,17 @@ void DWARFUnitSectionBase::parse(DWARFCo
   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,

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp?rev=313659&r1=313658&r2=313659&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp Tue Sep 19 11:36:11 2017
@@ -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;
 }
 




More information about the llvm-commits mailing list