[PDB] Don't crash on /debug:fastlink PDBs.

Apparently support for /debug:fastlink PDBs isn't part of the
DIA SDK (!), and it was causing llvm-pdbdump to crash because
we weren't checking for a null pointer return value.  This
manifests when calling findChildren on the IDiaSymbol, and
it returns E_NOTIMPL.

llvm-svn: 304982
This commit is contained in:
Zachary Turner 2017-06-08 16:00:40 +00:00
parent 5579eb0a7a
commit 15eb237fd3
3 changed files with 74 additions and 63 deletions

View File

@ -89,6 +89,8 @@ public:
template <typename T> std::unique_ptr<T> findOneChild() const { template <typename T> std::unique_ptr<T> findOneChild() const {
auto Enumerator(findAllChildren<T>()); auto Enumerator(findAllChildren<T>());
if (!Enumerator)
return nullptr;
return Enumerator->getNext(); return Enumerator->getNext();
} }
@ -97,6 +99,8 @@ public:
template <typename T> template <typename T>
std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const { std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const {
auto BaseIter = RawSymbol->findChildren(T::Tag); auto BaseIter = RawSymbol->findChildren(T::Tag);
if (!BaseIter)
return nullptr;
return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter)); return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter));
} }
std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const; std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const;

View File

@ -372,8 +372,11 @@ DIARawSymbol::findChildren(PDB_SymType Type) const {
enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
CComPtr<IDiaEnumSymbols> DiaEnumerator; CComPtr<IDiaEnumSymbols> DiaEnumerator;
if (S_OK != Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) if (S_OK !=
return nullptr; Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) {
if (S_OK != Symbol->findChildren(EnumVal, nullptr, nsNone, &DiaEnumerator))
return nullptr;
}
return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
} }

View File

@ -135,80 +135,84 @@ filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void TypeDumper::start(const PDBSymbolExe &Exe) { void TypeDumper::start(const PDBSymbolExe &Exe) {
auto Children = Exe.findAllChildren();
if (opts::pretty::Enums) { if (opts::pretty::Enums) {
auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>(); if (auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>()) {
Printer.NewLine(); Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums"; WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
Printer << ": (" << Enums->getChildCount() << " items)"; Printer << ": (" << Enums->getChildCount() << " items)";
Printer.Indent(); Printer.Indent();
while (auto Enum = Enums->getNext()) while (auto Enum = Enums->getNext())
Enum->dump(*this); Enum->dump(*this);
Printer.Unindent(); Printer.Unindent();
}
} }
if (opts::pretty::Typedefs) { if (opts::pretty::Typedefs) {
auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>(); if (auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>()) {
Printer.NewLine(); Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs"; WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
Printer << ": (" << Typedefs->getChildCount() << " items)"; Printer << ": (" << Typedefs->getChildCount() << " items)";
Printer.Indent(); Printer.Indent();
while (auto Typedef = Typedefs->getNext()) while (auto Typedef = Typedefs->getNext())
Typedef->dump(*this); Typedef->dump(*this);
Printer.Unindent(); Printer.Unindent();
}
} }
if (opts::pretty::Classes) { if (opts::pretty::Classes) {
auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>(); if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
uint32_t All = Classes->getChildCount(); uint32_t All = Classes->getChildCount();
Printer.NewLine(); Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes"; WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
bool Precompute = false; bool Precompute = false;
Precompute = Precompute =
(opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None); (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
// If we're using no sort mode, then we can start getting immediate output // If we're using no sort mode, then we can start getting immediate output
// from the tool by just filtering as we go, rather than processing // from the tool by just filtering as we go, rather than processing
// everything up front so that we can sort it. This makes the tool more // everything up front so that we can sort it. This makes the tool more
// responsive. So only precompute the filtered/sorted set of classes if // responsive. So only precompute the filtered/sorted set of classes if
// necessary due to the specified options. // necessary due to the specified options.
std::vector<LayoutPtr> Filtered; std::vector<LayoutPtr> Filtered;
uint32_t Shown = All; uint32_t Shown = All;
if (Precompute) { if (Precompute) {
Filtered = filterAndSortClassDefs(Printer, *Classes, All); Filtered = filterAndSortClassDefs(Printer, *Classes, All);
Shown = Filtered.size(); Shown = Filtered.size();
}
Printer << ": (Showing " << Shown << " items";
if (Shown < All)
Printer << ", " << (All - Shown) << " filtered";
Printer << ")";
Printer.Indent();
// If we pre-computed, iterate the filtered/sorted list, otherwise iterate
// the DIA enumerator and filter on the fly.
if (Precompute) {
for (auto &Class : Filtered)
dumpClassLayout(*Class);
} else {
while (auto Class = Classes->getNext()) {
if (Class->getUnmodifiedTypeId() != 0)
continue;
if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
continue;
auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
continue;
dumpClassLayout(*Layout);
} }
}
Printer.Unindent(); Printer << ": (Showing " << Shown << " items";
if (Shown < All)
Printer << ", " << (All - Shown) << " filtered";
Printer << ")";
Printer.Indent();
// If we pre-computed, iterate the filtered/sorted list, otherwise iterate
// the DIA enumerator and filter on the fly.
if (Precompute) {
for (auto &Class : Filtered)
dumpClassLayout(*Class);
} else {
while (auto Class = Classes->getNext()) {
if (Class->getUnmodifiedTypeId() != 0)
continue;
if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
continue;
auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
continue;
dumpClassLayout(*Layout);
}
}
Printer.Unindent();
}
} }
} }