forked from OSchip/llvm-project
[llvm-pdbdump] Only build the TypeDatabase if necessary.
Building the type database is expensive, and can take multiple minutes for large PDBs. But we only need it in certain cases depending on what command line options are specified. So only build it when we know we're about to need it. llvm-svn: 302204
This commit is contained in:
parent
9aff829f78
commit
20d773c4af
|
@ -609,11 +609,8 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||||
VerLabel = "IPI Version";
|
VerLabel = "IPI Version";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
|
if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
|
||||||
if (IsSilentDatabaseBuild) {
|
return Error::success();
|
||||||
outs().flush();
|
|
||||||
errs() << "Building Type Information For " << Label << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
|
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
|
||||||
: File.getPDBIpiStream();
|
: File.getPDBIpiStream();
|
||||||
|
@ -623,38 +620,43 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||||
std::unique_ptr<DictScope> StreamScope;
|
std::unique_ptr<DictScope> StreamScope;
|
||||||
std::unique_ptr<ListScope> RecordScope;
|
std::unique_ptr<ListScope> RecordScope;
|
||||||
|
|
||||||
if (!IsSilentDatabaseBuild) {
|
StreamScope = llvm::make_unique<DictScope>(P, Label);
|
||||||
StreamScope = llvm::make_unique<DictScope>(P, Label);
|
P.printNumber(VerLabel, Tpi->getTpiVersion());
|
||||||
P.printNumber(VerLabel, Tpi->getTpiVersion());
|
P.printNumber("Record count", Tpi->NumTypeRecords());
|
||||||
P.printNumber("Record count", Tpi->NumTypeRecords());
|
|
||||||
|
Optional<TypeDatabase> &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<TypeVisitorCallbacks>> Visitors;
|
||||||
|
|
||||||
|
Visitors.push_back(make_unique<TypeDeserializer>());
|
||||||
|
if (!StreamDB.hasValue()) {
|
||||||
|
StreamDB.emplace();
|
||||||
|
Visitors.push_back(make_unique<TypeDatabaseVisitor>(*StreamDB));
|
||||||
}
|
}
|
||||||
|
// If we're in dump mode, add a dumper with the appropriate detail level.
|
||||||
|
if (DumpRecords) {
|
||||||
|
std::unique_ptr<TypeVisitorCallbacks> Dumper;
|
||||||
|
if (opts::raw::CompactRecords)
|
||||||
|
Dumper = make_unique<CompactTypeDumpVisitor>(*StreamDB, &P);
|
||||||
|
else {
|
||||||
|
assert(TypeDB.hasValue());
|
||||||
|
|
||||||
TypeDatabase &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
|
auto X = make_unique<TypeDumpVisitor>(*TypeDB, &P, false);
|
||||||
|
if (StreamIdx == StreamIPI)
|
||||||
TypeDatabaseVisitor DBV(StreamDB);
|
X->setItemDB(*ItemDB);
|
||||||
CompactTypeDumpVisitor CTDV(StreamDB, &P);
|
Dumper = std::move(X);
|
||||||
TypeDumpVisitor TDV(TypeDB, &P, false);
|
}
|
||||||
if (StreamIdx == StreamIPI)
|
Visitors.push_back(std::move(Dumper));
|
||||||
TDV.setItemDB(ItemDB);
|
}
|
||||||
RecordBytesVisitor RBV(P);
|
if (DumpRecordBytes)
|
||||||
TypeDeserializer Deserializer;
|
Visitors.push_back(make_unique<RecordBytesVisitor>(P));
|
||||||
|
|
||||||
// We always need to deserialize and add it to the type database. This is
|
// We always need to deserialize and add it to the type database. This is
|
||||||
// true if even if we're not dumping anything, because we could need the
|
// true if even if we're not dumping anything, because we could need the
|
||||||
// type database for the purposes of dumping symbols.
|
// type database for the purposes of dumping symbols.
|
||||||
TypeVisitorCallbackPipeline Pipeline;
|
TypeVisitorCallbackPipeline Pipeline;
|
||||||
Pipeline.addCallbackToPipeline(Deserializer);
|
for (const auto &V : Visitors)
|
||||||
Pipeline.addCallbackToPipeline(DBV);
|
Pipeline.addCallbackToPipeline(*V);
|
||||||
|
|
||||||
// If we're in dump mode, add a dumper with the appropriate detail level.
|
|
||||||
if (DumpRecords) {
|
|
||||||
if (opts::raw::CompactRecords)
|
|
||||||
Pipeline.addCallbackToPipeline(CTDV);
|
|
||||||
else
|
|
||||||
Pipeline.addCallbackToPipeline(TDV);
|
|
||||||
}
|
|
||||||
if (DumpRecordBytes)
|
|
||||||
Pipeline.addCallbackToPipeline(RBV);
|
|
||||||
|
|
||||||
CVTypeVisitor Visitor(Pipeline);
|
CVTypeVisitor Visitor(Pipeline);
|
||||||
|
|
||||||
|
@ -700,19 +702,42 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsSilentDatabaseBuild) {
|
ListScope L(P, "TypeIndexOffsets");
|
||||||
ListScope L(P, "TypeIndexOffsets");
|
for (const auto &IO : Tpi->getTypeIndexOffsets()) {
|
||||||
for (const auto &IO : Tpi->getTypeIndexOffsets()) {
|
P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
|
||||||
P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
|
(uint32_t)IO.Offset)
|
||||||
(uint32_t)IO.Offset)
|
.str());
|
||||||
.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
P.flush();
|
P.flush();
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error LLVMOutputStyle::buildTypeDatabase(uint32_t SN) {
|
||||||
|
assert(SN == StreamIPI || SN == StreamTPI);
|
||||||
|
|
||||||
|
auto &DB = (SN == StreamIPI) ? ItemDB : TypeDB;
|
||||||
|
|
||||||
|
if (DB.hasValue())
|
||||||
|
return Error::success();
|
||||||
|
|
||||||
|
DB.emplace();
|
||||||
|
|
||||||
|
TypeVisitorCallbackPipeline Pipeline;
|
||||||
|
TypeDeserializer Deserializer;
|
||||||
|
TypeDatabaseVisitor DBV(*DB);
|
||||||
|
Pipeline.addCallbackToPipeline(Deserializer);
|
||||||
|
Pipeline.addCallbackToPipeline(DBV);
|
||||||
|
|
||||||
|
auto Tpi =
|
||||||
|
(SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
|
||||||
|
if (!Tpi)
|
||||||
|
return Tpi.takeError();
|
||||||
|
|
||||||
|
CVTypeVisitor Visitor(Pipeline);
|
||||||
|
return Visitor.visitTypeStream(Tpi->types(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
Error LLVMOutputStyle::dumpDbiStream() {
|
Error LLVMOutputStyle::dumpDbiStream() {
|
||||||
bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
|
bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
|
||||||
opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
|
opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
|
||||||
|
@ -785,8 +810,11 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (ShouldDumpSymbols) {
|
if (ShouldDumpSymbols) {
|
||||||
|
if (auto EC = buildTypeDatabase(StreamTPI))
|
||||||
|
return EC;
|
||||||
|
|
||||||
ListScope SS(P, "Symbols");
|
ListScope SS(P, "Symbols");
|
||||||
codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
|
codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
|
||||||
bool HadError = false;
|
bool HadError = false;
|
||||||
for (auto S : ModS.symbols(&HadError)) {
|
for (auto S : ModS.symbols(&HadError)) {
|
||||||
DictScope LL(P, "");
|
DictScope LL(P, "");
|
||||||
|
@ -807,8 +835,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
||||||
}
|
}
|
||||||
if (opts::raw::DumpLineInfo) {
|
if (opts::raw::DumpLineInfo) {
|
||||||
ListScope SS(P, "LineInfo");
|
ListScope SS(P, "LineInfo");
|
||||||
|
if (auto EC = buildTypeDatabase(StreamIPI))
|
||||||
|
return EC;
|
||||||
|
|
||||||
C13RawVisitor V(P, File, ItemDB);
|
C13RawVisitor V(P, File, *ItemDB);
|
||||||
if (auto EC = codeview::visitModuleDebugFragments(
|
if (auto EC = codeview::visitModuleDebugFragments(
|
||||||
ModS.linesAndChecksums(), V))
|
ModS.linesAndChecksums(), V))
|
||||||
return EC;
|
return EC;
|
||||||
|
@ -925,7 +955,10 @@ Error LLVMOutputStyle::dumpPublicsStream() {
|
||||||
P.printList("Section Offsets", Publics->getSectionOffsets(),
|
P.printList("Section Offsets", Publics->getSectionOffsets(),
|
||||||
printSectionOffset);
|
printSectionOffset);
|
||||||
ListScope L(P, "Symbols");
|
ListScope L(P, "Symbols");
|
||||||
codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
|
if (auto EC = buildTypeDatabase(StreamTPI))
|
||||||
|
return EC;
|
||||||
|
|
||||||
|
codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
|
||||||
bool HadError = false;
|
bool HadError = false;
|
||||||
for (auto S : Publics->getSymbols(&HadError)) {
|
for (auto S : Publics->getSymbols(&HadError)) {
|
||||||
DictScope DD(P, "");
|
DictScope DD(P, "");
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "OutputStyle.h"
|
#include "OutputStyle.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
||||||
#include "llvm/Support/ScopedPrinter.h"
|
#include "llvm/Support/ScopedPrinter.h"
|
||||||
|
@ -28,6 +29,8 @@ public:
|
||||||
Error dump() override;
|
Error dump() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Error buildTypeDatabase(uint32_t SN);
|
||||||
|
|
||||||
Error dumpFileHeaders();
|
Error dumpFileHeaders();
|
||||||
Error dumpStreamSummary();
|
Error dumpStreamSummary();
|
||||||
Error dumpFreePageMap();
|
Error dumpFreePageMap();
|
||||||
|
@ -51,8 +54,8 @@ private:
|
||||||
|
|
||||||
PDBFile &File;
|
PDBFile &File;
|
||||||
ScopedPrinter P;
|
ScopedPrinter P;
|
||||||
codeview::TypeDatabase TypeDB;
|
Optional<codeview::TypeDatabase> TypeDB;
|
||||||
codeview::TypeDatabase ItemDB;
|
Optional<codeview::TypeDatabase> ItemDB;
|
||||||
SmallVector<std::string, 32> StreamPurposes;
|
SmallVector<std::string, 32> StreamPurposes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue