summaryrefslogtreecommitdiff
path: root/tools/llvm-pdbutil/DumpOutputStyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-pdbutil/DumpOutputStyle.cpp')
-rw-r--r--tools/llvm-pdbutil/DumpOutputStyle.cpp111
1 files changed, 86 insertions, 25 deletions
diff --git a/tools/llvm-pdbutil/DumpOutputStyle.cpp b/tools/llvm-pdbutil/DumpOutputStyle.cpp
index f76635f9e5118..a1f919b4dd065 100644
--- a/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -37,6 +37,7 @@
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
@@ -116,12 +117,14 @@ Error DumpOutputStyle::dump() {
return EC;
}
- if (opts::dump::DumpTypes || opts::dump::DumpTypeExtras) {
+ if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
+ opts::dump::DumpTypeExtras) {
if (auto EC = dumpTpiStream(StreamTPI))
return EC;
}
- if (opts::dump::DumpIds || opts::dump::DumpIdExtras) {
+ if (opts::dump::DumpIds || !opts::dump::DumpIdIndex.empty() ||
+ opts::dump::DumpIdExtras) {
if (auto EC = dumpTpiStream(StreamIPI))
return EC;
}
@@ -620,6 +623,76 @@ Error DumpOutputStyle::dumpStringTable() {
return Error::success();
}
+static void buildDepSet(LazyRandomTypeCollection &Types,
+ ArrayRef<TypeIndex> Indices,
+ std::map<TypeIndex, CVType> &DepSet) {
+ SmallVector<TypeIndex, 4> DepList;
+ for (const auto &I : Indices) {
+ TypeIndex TI(I);
+ if (DepSet.find(TI) != DepSet.end() || TI.isSimple() || TI.isNoneType())
+ continue;
+
+ CVType Type = Types.getType(TI);
+ DepSet[TI] = Type;
+ codeview::discoverTypeIndices(Type, DepList);
+ buildDepSet(Types, DepList, DepSet);
+ }
+}
+
+static void dumpFullTypeStream(LinePrinter &Printer,
+ LazyRandomTypeCollection &Types,
+ TpiStream &Stream, bool Bytes, bool Extras) {
+ Printer.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
+ uint32_t Width =
+ NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
+
+ MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
+ Stream.getHashValues());
+
+ if (auto EC = codeview::visitTypeStream(Types, V)) {
+ Printer.formatLine("An error occurred dumping type records: {0}",
+ toString(std::move(EC)));
+ }
+}
+
+static void dumpPartialTypeStream(LinePrinter &Printer,
+ LazyRandomTypeCollection &Types,
+ TpiStream &Stream, ArrayRef<TypeIndex> TiList,
+ bool Bytes, bool Extras, bool Deps) {
+ uint32_t Width =
+ NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
+
+ MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
+ Stream.getHashValues());
+
+ if (opts::dump::DumpTypeDependents) {
+ // If we need to dump all dependents, then iterate each index and find
+ // all dependents, adding them to a map ordered by TypeIndex.
+ std::map<TypeIndex, CVType> DepSet;
+ buildDepSet(Types, TiList, DepSet);
+
+ Printer.formatLine(
+ "Showing {0:N} records and their dependents ({1:N} records total)",
+ TiList.size(), DepSet.size());
+
+ for (auto &Dep : DepSet) {
+ if (auto EC = codeview::visitTypeRecord(Dep.second, Dep.first, V))
+ Printer.formatLine("An error occurred dumping type record {0}: {1}",
+ Dep.first, toString(std::move(EC)));
+ }
+ } else {
+ Printer.formatLine("Showing {0:N} records.", TiList.size());
+
+ for (const auto &I : TiList) {
+ TypeIndex TI(I);
+ CVType Type = Types.getType(TI);
+ if (auto EC = codeview::visitTypeRecord(Type, TI, V))
+ Printer.formatLine("An error occurred dumping type record {0}: {1}", TI,
+ toString(std::move(EC)));
+ }
+ }
+}
+
Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
@@ -659,27 +732,13 @@ Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
auto &Types = Err(initializeTypes(StreamIdx));
- if (DumpTypes) {
- P.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
- uint32_t Width =
- NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
-
- MinimalTypeDumpVisitor V(P, Width + 2, DumpBytes, DumpExtras, Types,
- Stream.getHashValues());
-
- if (Indices.empty()) {
- if (auto EC = codeview::visitTypeStream(Types, V)) {
- P.formatLine("An error occurred dumping type records: {0}",
- toString(std::move(EC)));
- }
- } else {
- for (const auto &I : Indices) {
- TypeIndex TI(I);
- CVType Type = Types.getType(TI);
- if (auto EC = codeview::visitTypeRecord(Type, TI, V))
- P.formatLine("An error occurred dumping type record {0}: {1}", TI,
- toString(std::move(EC)));
- }
+ if (DumpTypes || !Indices.empty()) {
+ if (Indices.empty())
+ dumpFullTypeStream(P, Types, Stream, DumpBytes, DumpExtras);
+ else {
+ std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
+ dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,
+ opts::dump::DumpTypeDependents);
}
}
@@ -775,7 +834,8 @@ Error DumpOutputStyle::dumpModuleSyms() {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
CVSymbolVisitor Visitor(Pipeline);
- if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray())) {
+ auto SS = ModS.getSymbolsSubstream();
+ if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) {
P.formatLine("Error while processing symbol records. {0}",
toString(std::move(EC)));
continue;
@@ -804,13 +864,14 @@ Error DumpOutputStyle::dumpPublics() {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
CVSymbolVisitor Visitor(Pipeline);
+
auto ExpectedSymbols = Publics.getSymbolArray();
if (!ExpectedSymbols) {
P.formatLine("Could not read public symbol record stream");
return Error::success();
}
- if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols))
+ if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols, 0))
P.formatLine("Error while processing public symbol records. {0}",
toString(std::move(EC)));