summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-08-21 14:53:25 +0000
committerZachary Turner <zturner@google.com>2017-08-21 14:53:25 +0000
commitd1de2f4f5e965d70053b0c0d20d99ad4a105f428 (patch)
treeee90fa721e95e1dfc93217e26d8eeaec8ab1f0a0 /llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
parent48c67c99651d431ec03edc2bdf11abdd24089d2c (diff)
downloadbcm5719-llvm-d1de2f4f5e965d70053b0c0d20d99ad4a105f428.tar.gz
bcm5719-llvm-d1de2f4f5e965d70053b0c0d20d99ad4a105f428.zip
[llvm-pdbutil] Add support for dumping detailed module stats.
This adds support for dumping a summary of module symbols and CodeView debug chunks. This option prints a table for each module of all of the symbols that occurred in the module and the number of times it occurred and total byte size. Then at the end it prints the totals for the entire file. Additionally, this patch adds the -jmc (just my code) option, which suppresses modules which are from external libraries or linker imports, so that you can focus only on the object files and libraries that originate from your own source code. llvm-svn: 311338
Diffstat (limited to 'llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp')
-rw-r--r--llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp174
1 files changed, 152 insertions, 22 deletions
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index 1e3e8e419a8..c573f606786 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -82,6 +82,12 @@ Error DumpOutputStyle::dump() {
P.NewLine();
}
+ if (opts::dump::DumpModuleStats.getNumOccurrences() > 0) {
+ if (auto EC = dumpModuleStats())
+ return EC;
+ P.NewLine();
+ }
+
if (opts::dump::DumpStringTable) {
if (auto EC = dumpStringTable())
return EC;
@@ -199,6 +205,77 @@ Error DumpOutputStyle::dumpFileSummary() {
return Error::success();
}
+static StatCollection getSymbolStats(ModuleDebugStreamRef MDS,
+ StatCollection &CumulativeStats) {
+ StatCollection Stats;
+ for (const auto &S : MDS.symbols(nullptr)) {
+ Stats.update(S.kind(), S.length());
+ CumulativeStats.update(S.kind(), S.length());
+ }
+ return Stats;
+}
+
+static StatCollection getChunkStats(ModuleDebugStreamRef MDS,
+ StatCollection &CumulativeStats) {
+ StatCollection Stats;
+ for (const auto &Chunk : MDS.subsections()) {
+ Stats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+ CumulativeStats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+ }
+ return Stats;
+}
+
+static inline std::string formatModuleDetailKind(DebugSubsectionKind K) {
+ return formatChunkKind(K, false);
+}
+
+static inline std::string formatModuleDetailKind(SymbolKind K) {
+ return formatSymbolKind(K);
+}
+
+template <typename Kind>
+static void printModuleDetailStats(LinePrinter &P, StringRef Label,
+ const StatCollection &Stats) {
+ P.NewLine();
+ P.formatLine(" {0}", Label);
+ AutoIndent Indent(P);
+ P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", "Total",
+ Stats.Totals.Count, Stats.Totals.Size);
+ P.formatLine("{0}", fmt_repeat('-', 74));
+ for (const auto &K : Stats.Individual) {
+ std::string KindName = formatModuleDetailKind(Kind(K.first));
+ P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", KindName,
+ K.second.Count, K.second.Size);
+ }
+}
+
+static bool isMyCode(const DbiModuleDescriptor &Desc) {
+ StringRef Name = Desc.getModuleName();
+ if (Name.startswith("Import:"))
+ return false;
+ if (Name.endswith_lower(".dll"))
+ return false;
+ if (Name.equals_lower("* linker *"))
+ return false;
+ if (Name.startswith_lower("f:\\binaries\\Intermediate\\vctools"))
+ return false;
+ if (Name.startswith_lower("f:\\dd\\vctools\\crt"))
+ return false;
+ return true;
+}
+
+static bool shouldDumpModule(uint32_t Modi, const DbiModuleDescriptor &Desc) {
+ if (opts::dump::JustMyCode && !isMyCode(Desc))
+ return false;
+
+ // If the arg was not specified on the command line, always dump all modules.
+ if (opts::dump::DumpModi.getNumOccurrences() == 0)
+ return true;
+
+ // Otherwise, only dump if this is the same module specified.
+ return (opts::dump::DumpModi == Modi);
+}
+
Error DumpOutputStyle::dumpStreamSummary() {
printHeader(P, "Streams");
@@ -207,12 +284,16 @@ Error DumpOutputStyle::dumpStreamSummary() {
AutoIndent Indent(P);
uint32_t StreamCount = File.getNumStreams();
+ uint32_t MaxStreamSize = File.getMaxStreamSize();
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
P.formatLine(
- "Stream {0}: [{1}] ({2} bytes)",
+ "Stream {0} ({1} bytes): [{2}]",
fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
- StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
+ fmt_align(File.getStreamByteSize(StreamIdx), AlignStyle::Right,
+ NumDigits(MaxStreamSize)),
+ StreamPurposes[StreamIdx].getLongName());
+
if (opts::dump::DumpStreamBlocks) {
auto Blocks = File.getStreamBlockList(StreamIdx);
std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
@@ -389,8 +470,10 @@ static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
uint32_t Count = Modules.getModuleCount();
uint32_t Digits = NumDigits(Count);
for (uint32_t I = 0; I < Count; ++I) {
- auto Descriptor = Modules.getModuleDescriptor(I);
- iterateOneModule(File, P, Descriptor, I, IndentLevel, Digits, Callback);
+ auto Desc = Modules.getModuleDescriptor(I);
+ if (!shouldDumpModule(I, Desc))
+ continue;
+ iterateOneModule(File, P, Desc, I, IndentLevel, Digits, Callback);
}
}
@@ -438,24 +521,21 @@ Error DumpOutputStyle::dumpModules() {
auto &Stream = Err(File.getPDBDbiStream());
const DbiModuleList &Modules = Stream.modules();
- uint32_t Count = Modules.getModuleCount();
- uint32_t Digits = NumDigits(Count);
- for (uint32_t I = 0; I < Count; ++I) {
- auto Modi = Modules.getModuleDescriptor(I);
- P.formatLine("Mod {0:4} | Name: `{1}`: ",
- fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
- P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
- P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
- Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
- Modi.hasECInfo());
- StringRef PdbFilePath =
- Err(Stream.getECName(Modi.getPdbFilePathNameIndex()));
- StringRef SrcFilePath =
- Err(Stream.getECName(Modi.getSourceFileNameIndex()));
- P.formatLine(" pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
- Modi.getPdbFilePathNameIndex(), PdbFilePath,
- Modi.getSourceFileNameIndex(), SrcFilePath);
- }
+ iterateModules(
+ File, P, 11, [&](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
+ auto Desc = Modules.getModuleDescriptor(Modi);
+ P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
+ P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
+ Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
+ Desc.hasECInfo());
+ StringRef PdbFilePath =
+ Err(Stream.getECName(Desc.getPdbFilePathNameIndex()));
+ StringRef SrcFilePath =
+ Err(Stream.getECName(Desc.getSourceFileNameIndex()));
+ P.formatLine("pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
+ Desc.getPdbFilePathNameIndex(), PdbFilePath,
+ Desc.getSourceFileNameIndex(), SrcFilePath);
+ });
return Error::success();
}
@@ -477,6 +557,56 @@ Error DumpOutputStyle::dumpModuleFiles() {
return Error::success();
}
+Error DumpOutputStyle::dumpModuleStats() {
+ printHeader(P, "Module Stats");
+
+ ExitOnError Err("Unexpected error processing modules: ");
+
+ StatCollection SymStats;
+ StatCollection ChunkStats;
+ auto &Stream = Err(File.getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ uint32_t ModCount = Modules.getModuleCount();
+
+ iterateModules(File, P, 0, [&](uint32_t Modi,
+ StringsAndChecksumsPrinter &Strings) {
+ DbiModuleDescriptor Desc = Modules.getModuleDescriptor(Modi);
+ uint32_t StreamIdx = Desc.getModuleStreamIndex();
+
+ if (StreamIdx == kInvalidStreamIndex) {
+ P.formatLine("Mod {0} (debug info not present): [{1}]",
+ fmt_align(Modi, AlignStyle::Right, NumDigits(ModCount)),
+ Desc.getModuleName());
+ return;
+ }
+
+ P.formatLine("Stream {0}, {1} bytes", StreamIdx,
+ File.getStreamByteSize(StreamIdx));
+
+ ModuleDebugStreamRef MDS(Desc, File.createIndexedStream(StreamIdx));
+ if (auto EC = MDS.reload()) {
+ P.printLine("- Error parsing debug info stream");
+ consumeError(std::move(EC));
+ return;
+ }
+
+ printModuleDetailStats<SymbolKind>(P, "Symbols",
+ getSymbolStats(MDS, SymStats));
+ printModuleDetailStats<DebugSubsectionKind>(P, "Chunks",
+ getChunkStats(MDS, ChunkStats));
+ });
+
+ P.printLine(" Summary |");
+ AutoIndent Indent(P, 4);
+ if (SymStats.Totals.Count > 0) {
+ printModuleDetailStats<SymbolKind>(P, "Symbols", SymStats);
+ printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", ChunkStats);
+ }
+
+ return Error::success();
+}
+
static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
uint32_t Start, const LineColumnEntry &E) {
const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
OpenPOWER on IntegriCloud