Skip to content

Commit e79dda3

Browse files
committed
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. llvm-svn: 313659
1 parent b6e60c8 commit e79dda3

File tree

4 files changed

+71
-20
lines changed

4 files changed

+71
-20
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ class DWARFUnitSectionBase {
4747
/// Returns the Unit that contains the given section offset in the
4848
/// same section this Unit originated from.
4949
virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
50+
virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0;
5051

5152
void parse(DWARFContext &C, const DWARFSection &Section);
5253
void parseDWO(DWARFContext &C, const DWARFSection &DWOSection,
53-
DWARFUnitIndex *Index = nullptr);
54+
bool Lazy = false);
5455

5556
protected:
5657
~DWARFUnitSectionBase() = default;
@@ -59,7 +60,7 @@ class DWARFUnitSectionBase {
5960
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
6061
StringRef SS, const DWARFSection &SOS,
6162
const DWARFSection *AOS, const DWARFSection &LS,
62-
bool isLittleEndian, bool isDWO) = 0;
63+
bool isLittleEndian, bool isDWO, bool Lazy) = 0;
6364
};
6465

6566
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
@@ -70,6 +71,7 @@ template<typename UnitType>
7071
class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
7172
public DWARFUnitSectionBase {
7273
bool Parsed = false;
74+
std::function<std::unique_ptr<UnitType>(uint32_t)> Parser;
7375

7476
public:
7577
using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>;
@@ -82,29 +84,76 @@ class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
8284
[](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
8385
return LHS < RHS->getNextUnitOffset();
8486
});
85-
if (CU != this->end())
87+
if (CU != this->end() && (*CU)->getOffset() <= Offset)
8688
return CU->get();
8789
return nullptr;
8890
}
91+
UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override {
92+
const auto *CUOff = E.getOffset(DW_SECT_INFO);
93+
if (!CUOff)
94+
return nullptr;
95+
96+
auto Offset = CUOff->Offset;
97+
98+
auto *CU = std::upper_bound(
99+
this->begin(), this->end(), CUOff->Offset,
100+
[](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
101+
return LHS < RHS->getNextUnitOffset();
102+
});
103+
if (CU != this->end() && (*CU)->getOffset() <= Offset)
104+
return CU->get();
105+
106+
if (!Parser)
107+
return nullptr;
108+
109+
auto U = Parser(Offset);
110+
if (!U)
111+
U = nullptr;
112+
113+
auto *NewCU = U.get();
114+
this->insert(CU, std::move(U));
115+
return NewCU;
116+
}
89117

90118
private:
91119
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
92120
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
93121
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
94-
const DWARFSection &LS, bool LE, bool IsDWO) override {
122+
const DWARFSection &LS, bool LE, bool IsDWO,
123+
bool Lazy) override {
95124
if (Parsed)
96125
return;
97-
const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
98126
DataExtractor Data(Section.Data, LE, 0);
127+
if (!Parser) {
128+
const DWARFUnitIndex *Index = nullptr;
129+
if (IsDWO)
130+
Index = &getDWARFUnitIndex(Context, UnitType::Section);
131+
Parser = [=, &Context, &Section, &SOS,
132+
&LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
133+
if (!Data.isValidOffset(Offset))
134+
return nullptr;
135+
auto U = llvm::make_unique<UnitType>(
136+
Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
137+
Index ? Index->getFromOffset(Offset) : nullptr);
138+
if (!U->extract(Data, &Offset))
139+
return nullptr;
140+
return U;
141+
};
142+
}
143+
if (Lazy)
144+
return;
145+
auto I = this->begin();
99146
uint32_t Offset = 0;
100147
while (Data.isValidOffset(Offset)) {
101-
auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
102-
AOS, LS, LE, IsDWO, *this,
103-
Index.getFromOffset(Offset));
104-
if (!U->extract(Data, &Offset))
148+
if (I != this->end() && (*I)->getOffset() == Offset) {
149+
++I;
150+
continue;
151+
}
152+
auto U = Parser(Offset);
153+
if (!U)
105154
break;
106-
this->push_back(std::move(U));
107-
Offset = this->back()->getNextUnitOffset();
155+
Offset = U->getNextUnitOffset();
156+
I = std::next(this->insert(I, std::move(U)));
108157
}
109158
Parsed = true;
110159
}

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,12 +464,11 @@ void DWARFContext::dump(
464464
}
465465

466466
DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
467-
parseDWOCompileUnits();
467+
DWOCUs.parseDWO(*this, DObj->getInfoDWOSection(), true);
468468

469469
if (const auto &CUI = getCUIndex()) {
470470
if (const auto *R = CUI.getFromHash(Hash))
471-
if (auto CUOff = R->getOffset(DW_SECT_INFO))
472-
return DWOCUs.getUnitForOffset(CUOff->Offset);
471+
return DWOCUs.getUnitForIndexEntry(*R);
473472
return nullptr;
474473
}
475474

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
3333
const DWARFObject &D = C.getDWARFObj();
3434
parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(),
3535
D.getStringSection(), D.getStringOffsetSection(),
36-
&D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false);
36+
&D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false,
37+
false);
3738
}
3839

3940
void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
40-
const DWARFSection &DWOSection,
41-
DWARFUnitIndex *Index) {
41+
const DWARFSection &DWOSection, bool Lazy) {
4242
const DWARFObject &D = C.getDWARFObj();
4343
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(),
4444
D.getStringDWOSection(), D.getStringOffsetDWOSection(),
4545
&D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(),
46-
true);
46+
true, Lazy);
4747
}
4848

4949
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,

llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,12 @@ DWARFUnitIndex::Entry::getOffset() const {
165165
const DWARFUnitIndex::Entry *
166166
DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
167167
for (uint32_t i = 0; i != Header.NumBuckets; ++i)
168-
if (const auto &Contribs = Rows[i].Contributions)
169-
if (Contribs[InfoColumn].Offset == Offset)
168+
if (const auto &Contribs = Rows[i].Contributions) {
169+
const auto &InfoContrib = Contribs[InfoColumn];
170+
if (InfoContrib.Offset <= Offset &&
171+
Offset < (InfoContrib.Offset + InfoContrib.Length))
170172
return &Rows[i];
173+
}
171174
return nullptr;
172175
}
173176

0 commit comments

Comments
 (0)