summaryrefslogtreecommitdiffstats
path: root/llvm/tools
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
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')
-rw-r--r--llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp26
-rw-r--r--llvm/tools/llvm-pdbutil/BytesOutputStyle.h3
-rw-r--r--llvm/tools/llvm-pdbutil/Diff.cpp41
-rw-r--r--llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp174
-rw-r--r--llvm/tools/llvm-pdbutil/DumpOutputStyle.h29
-rw-r--r--llvm/tools/llvm-pdbutil/FormatUtil.cpp60
-rw-r--r--llvm/tools/llvm-pdbutil/FormatUtil.h5
-rw-r--r--llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp13
-rw-r--r--llvm/tools/llvm-pdbutil/StreamUtil.cpp140
-rw-r--r--llvm/tools/llvm-pdbutil/StreamUtil.h31
-rw-r--r--llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp12
-rw-r--r--llvm/tools/llvm-pdbutil/llvm-pdbutil.h2
12 files changed, 398 insertions, 138 deletions
diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp
index a50da5c580b..2b96c8f986a 100644
--- a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp
@@ -407,27 +407,6 @@ void BytesOutputStyle::dumpModuleC11() {
});
}
-static std::string formatChunkKind(DebugSubsectionKind Kind) {
- switch (Kind) {
- RETURN_CASE(DebugSubsectionKind, None, "none");
- RETURN_CASE(DebugSubsectionKind, Symbols, "symbols");
- RETURN_CASE(DebugSubsectionKind, Lines, "lines");
- RETURN_CASE(DebugSubsectionKind, StringTable, "strings");
- RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums");
- RETURN_CASE(DebugSubsectionKind, FrameData, "frames");
- RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines");
- RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi");
- RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme");
- RETURN_CASE(DebugSubsectionKind, ILLines, "il lines");
- RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map");
- RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map");
- RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
- "merged assembly input");
- RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva");
- }
- return formatUnknownEnum(Kind);
-}
-
void BytesOutputStyle::dumpModuleC13() {
printHeader(P, "Debug Chunks");
@@ -508,7 +487,8 @@ void BytesOutputStyle::dumpStreamBytes() {
P.formatLine("Stream {0}: Not present", Spec.SI);
continue;
}
- P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI],
- Spec.Begin, Spec.Size);
+ P.formatMsfStreamData("Data", File, Spec.SI,
+ StreamPurposes[Spec.SI].getShortName(), Spec.Begin,
+ Spec.Size);
}
}
diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.h b/llvm/tools/llvm-pdbutil/BytesOutputStyle.h
index 876178d56ab..aa5342998e5 100644
--- a/llvm/tools/llvm-pdbutil/BytesOutputStyle.h
+++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.h
@@ -12,6 +12,7 @@
#include "LinePrinter.h"
#include "OutputStyle.h"
+#include "StreamUtil.h"
#include "llvm/Support/Error.h"
@@ -60,7 +61,7 @@ private:
PDBFile &File;
LinePrinter P;
ExitOnError Err;
- SmallVector<std::string, 8> StreamPurposes;
+ SmallVector<StreamInfo, 8> StreamPurposes;
};
} // namespace pdb
} // namespace llvm
diff --git a/llvm/tools/llvm-pdbutil/Diff.cpp b/llvm/tools/llvm-pdbutil/Diff.cpp
index fb52545df0f..bd070499a5b 100644
--- a/llvm/tools/llvm-pdbutil/Diff.cpp
+++ b/llvm/tools/llvm-pdbutil/Diff.cpp
@@ -135,29 +135,28 @@ struct BinaryPathProvider {
struct StreamPurposeProvider {
explicit StreamPurposeProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
- DiffResult compare(const std::pair<StreamPurpose, std::string> &L,
- const std::pair<StreamPurpose, std::string> &R) {
- if (L.first != R.first)
+ DiffResult compare(const StreamInfo &L, const StreamInfo &R) {
+ if (L.getPurpose() != R.getPurpose())
return DiffResult::DIFFERENT;
- if (L.first == StreamPurpose::ModuleStream) {
+ if (L.getPurpose() == StreamPurpose::ModuleStream) {
BinaryPathProvider PathProvider(MaxLen);
- return PathProvider.compare(L.second, R.second);
+ return PathProvider.compare(L.getShortName(), R.getShortName());
}
- return (L.second == R.second) ? DiffResult::IDENTICAL
- : DiffResult::DIFFERENT;
+ return (L.getShortName() == R.getShortName()) ? DiffResult::IDENTICAL
+ : DiffResult::DIFFERENT;
}
- std::string format(const std::pair<StreamPurpose, std::string> &P,
- bool Right) {
- if (P.first == StreamPurpose::Other)
- return truncateStringBack(P.second, MaxLen);
- if (P.first == StreamPurpose::NamedStream)
- return truncateQuotedNameBack("Named Stream", P.second, MaxLen);
+ std::string format(const StreamInfo &P, bool Right) {
+ if (P.getPurpose() == StreamPurpose::Other ||
+ P.getPurpose() == StreamPurpose::Symbols)
+ return truncateStringBack(P.getShortName(), MaxLen);
+ if (P.getPurpose() == StreamPurpose::NamedStream)
+ return truncateQuotedNameBack("Named Stream", P.getShortName(), MaxLen);
- assert(P.first == StreamPurpose::ModuleStream);
+ assert(P.getPurpose() == StreamPurpose::ModuleStream);
uint32_t ExtraChars = strlen("Module \"\"");
BinaryPathProvider PathProvider(MaxLen - ExtraChars);
- std::string Result = PathProvider.format(P.second, Right);
+ std::string Result = PathProvider.format(P.getShortName(), Right);
return formatv("Module \"{0}\"", Result);
}
@@ -256,8 +255,8 @@ Error DiffStyle::diffStreamDirectory() {
truncateStringFront(File1.getFilePath(), 18),
truncateStringFront(File2.getFilePath(), 18));
- SmallVector<std::pair<StreamPurpose, std::string>, 32> P;
- SmallVector<std::pair<StreamPurpose, std::string>, 32> Q;
+ SmallVector<StreamInfo, 32> P;
+ SmallVector<StreamInfo, 32> Q;
discoverStreamPurposes(File1, P);
discoverStreamPurposes(File2, Q);
D.print("Stream Count", File1.getNumStreams(), File2.getNumStreams());
@@ -486,10 +485,10 @@ static void diffOneModule(DiffPrinter &D, const IndexedModuleDescriptor &Item,
IndexedModuleDescriptorList &Other,
bool ItemIsRight) {
StreamPurposeProvider HeaderProvider(70);
- std::pair<StreamPurpose, std::string> Header;
- Header.first = StreamPurpose::ModuleStream;
- Header.second = Item.second.getModuleName();
- D.printFullRow(HeaderProvider.format(Header, ItemIsRight));
+ StreamInfo Info = StreamInfo::createModuleStream(
+ Item.second.getModuleName(), Item.second.getModuleStreamIndex(),
+ Item.first);
+ D.printFullRow(HeaderProvider.format(Info, ItemIsRight));
const auto *L = &Item;
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
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index 383388f1b15..497c51fdbe4 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -12,7 +12,9 @@
#include "LinePrinter.h"
#include "OutputStyle.h"
+#include "StreamUtil.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
@@ -29,7 +31,31 @@ class LazyRandomTypeCollection;
namespace pdb {
class GSIHashTable;
+struct StatCollection {
+ struct Stat {
+ Stat() {}
+ Stat(uint32_t Count, uint32_t Size) : Count(Count), Size(Size) {}
+ uint32_t Count = 0;
+ uint32_t Size = 0;
+
+ void update(uint32_t RecordSize) {
+ ++Count;
+ Size += RecordSize;
+ }
+ };
+
+ void update(uint32_t Kind, uint32_t RecordSize) {
+ Totals.update(RecordSize);
+ auto Iter = Individual.try_emplace(Kind, 1, RecordSize);
+ if (!Iter.second)
+ Iter.first->second.update(RecordSize);
+ }
+ Stat Totals;
+ DenseMap<uint32_t, Stat> Individual;
+};
+
class DumpOutputStyle : public OutputStyle {
+
public:
DumpOutputStyle(PDBFile &File);
@@ -40,6 +66,7 @@ private:
Error dumpFileSummary();
Error dumpStreamSummary();
+ Error dumpModuleStats();
Error dumpStringTable();
Error dumpLines();
Error dumpInlineeLines();
@@ -62,7 +89,7 @@ private:
LinePrinter P;
std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
- SmallVector<std::string, 32> StreamPurposes;
+ SmallVector<StreamInfo, 32> StreamPurposes;
};
} // namespace pdb
} // namespace llvm
diff --git a/llvm/tools/llvm-pdbutil/FormatUtil.cpp b/llvm/tools/llvm-pdbutil/FormatUtil.cpp
index 039b1b900f3..eca0751a7ac 100644
--- a/llvm/tools/llvm-pdbutil/FormatUtil.cpp
+++ b/llvm/tools/llvm-pdbutil/FormatUtil.cpp
@@ -11,10 +11,12 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
+using namespace llvm::codeview;
using namespace llvm::pdb;
std::string llvm::pdb::truncateStringBack(StringRef S, uint32_t MaxLen) {
@@ -97,6 +99,64 @@ std::string llvm::pdb::typesetStringList(uint32_t IndentLevel,
return Result;
}
+std::string llvm::pdb::formatChunkKind(DebugSubsectionKind Kind,
+ bool Friendly) {
+ if (Friendly) {
+ switch (Kind) {
+ RETURN_CASE(DebugSubsectionKind, None, "none");
+ RETURN_CASE(DebugSubsectionKind, Symbols, "symbols");
+ RETURN_CASE(DebugSubsectionKind, Lines, "lines");
+ RETURN_CASE(DebugSubsectionKind, StringTable, "strings");
+ RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums");
+ RETURN_CASE(DebugSubsectionKind, FrameData, "frames");
+ RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines");
+ RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi");
+ RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme");
+ RETURN_CASE(DebugSubsectionKind, ILLines, "il lines");
+ RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map");
+ RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map");
+ RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
+ "merged assembly input");
+ RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva");
+ }
+ } else {
+ switch (Kind) {
+ RETURN_CASE(DebugSubsectionKind, None, "none");
+ RETURN_CASE(DebugSubsectionKind, Symbols, "DEBUG_S_SYMBOLS");
+ RETURN_CASE(DebugSubsectionKind, Lines, "DEBUG_S_LINES");
+ RETURN_CASE(DebugSubsectionKind, StringTable, "DEBUG_S_STRINGTABLE");
+ RETURN_CASE(DebugSubsectionKind, FileChecksums, "DEBUG_S_FILECHKSMS");
+ RETURN_CASE(DebugSubsectionKind, FrameData, "DEBUG_S_FRAMEDATA");
+ RETURN_CASE(DebugSubsectionKind, InlineeLines, "DEBUG_S_INLINEELINES");
+ RETURN_CASE(DebugSubsectionKind, CrossScopeImports,
+ "DEBUG_S_CROSSSCOPEIMPORTS");
+ RETURN_CASE(DebugSubsectionKind, CrossScopeExports,
+ "DEBUG_S_CROSSSCOPEEXPORTS");
+ RETURN_CASE(DebugSubsectionKind, ILLines, "DEBUG_S_IL_LINES");
+ RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap,
+ "DEBUG_S_FUNC_MDTOKEN_MAP");
+ RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap,
+ "DEBUG_S_TYPE_MDTOKEN_MAP");
+ RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
+ "DEBUG_S_MERGED_ASSEMBLYINPUT");
+ RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA,
+ "DEBUG_S_COFF_SYMBOL_RVA");
+ }
+ }
+ return formatUnknownEnum(Kind);
+}
+
+std::string llvm::pdb::formatSymbolKind(SymbolKind K) {
+ switch (uint32_t(K)) {
+#define SYMBOL_RECORD(EnumName, value, name) \
+ case EnumName: \
+ return #EnumName;
+#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName)
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+ }
+ return formatUnknownEnum(K);
+}
+
std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) {
return formatv("{0:4}:{1:4}", Segment, Offset);
}
diff --git a/llvm/tools/llvm-pdbutil/FormatUtil.h b/llvm/tools/llvm-pdbutil/FormatUtil.h
index 34fe4ee455c..7804a1f0e23 100644
--- a/llvm/tools/llvm-pdbutil/FormatUtil.h
+++ b/llvm/tools/llvm-pdbutil/FormatUtil.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
@@ -64,6 +65,10 @@ std::string typesetItemList(ArrayRef<std::string> Opts, uint32_t IndentLevel,
std::string typesetStringList(uint32_t IndentLevel,
ArrayRef<StringRef> Strings);
+std::string formatChunkKind(codeview::DebugSubsectionKind Kind,
+ bool Friendly = true);
+std::string formatSymbolKind(codeview::SymbolKind K);
+
/// Returns the number of digits in the given integer.
inline int NumDigits(uint64_t N) {
if (N < 10ULL)
diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
index 2413abf812d..0d7c5885f34 100644
--- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
+++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -24,17 +24,6 @@ using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
-static std::string getSymbolKindName(SymbolKind K) {
- switch (uint32_t(K)) {
-#define SYMBOL_RECORD(EnumName, value, name) \
- case EnumName: \
- return #EnumName;
-#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName)
-#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
- }
- return "";
-}
-
static std::string formatLocalSymFlags(uint32_t IndentLevel,
LocalSymFlags Flags) {
std::vector<std::string> Opts;
@@ -378,7 +367,7 @@ Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record,
// append to the existing line.
P.formatLine("{0} | {1} [size = {2}]",
fmt_align(Offset, AlignStyle::Right, 6),
- getSymbolKindName(Record.Type), Record.length());
+ formatSymbolKind(Record.Type), Record.length());
P.Indent();
return Error::success();
}
diff --git a/llvm/tools/llvm-pdbutil/StreamUtil.cpp b/llvm/tools/llvm-pdbutil/StreamUtil.cpp
index 4d352004dec..991c99aa868 100644
--- a/llvm/tools/llvm-pdbutil/StreamUtil.cpp
+++ b/llvm/tools/llvm-pdbutil/StreamUtil.cpp
@@ -22,9 +22,57 @@
using namespace llvm;
using namespace llvm::pdb;
-void llvm::pdb::discoverStreamPurposes(
- PDBFile &File,
- SmallVectorImpl<std::pair<StreamPurpose, std::string>> &Purposes) {
+std::string StreamInfo::getLongName() const {
+ if (Purpose == StreamPurpose::NamedStream)
+ return formatv("Named Stream \"{0}\"", Name).str();
+ if (Purpose == StreamPurpose::ModuleStream)
+ return formatv("Module \"{0}\"", Name).str();
+ return Name;
+}
+
+StreamInfo StreamInfo::createStream(StreamPurpose Purpose, StringRef Name,
+ uint32_t StreamIndex) {
+ StreamInfo Result;
+ Result.Name = Name;
+ Result.StreamIndex = StreamIndex;
+ Result.Purpose = Purpose;
+ return Result;
+}
+
+StreamInfo StreamInfo::createModuleStream(StringRef Module,
+ uint32_t StreamIndex, uint32_t Modi) {
+ StreamInfo Result;
+ Result.Name = Module;
+ Result.StreamIndex = StreamIndex;
+ Result.ModuleIndex = Modi;
+ Result.Purpose = StreamPurpose::ModuleStream;
+ return Result;
+}
+
+static inline StreamInfo otherStream(StringRef Label, uint32_t Idx) {
+ return StreamInfo::createStream(StreamPurpose::Other, Label, Idx);
+}
+
+static inline StreamInfo namedStream(StringRef Label, uint32_t Idx) {
+ return StreamInfo::createStream(StreamPurpose::NamedStream, Label, Idx);
+}
+
+static inline StreamInfo symbolStream(StringRef Label, uint32_t Idx) {
+ return StreamInfo::createStream(StreamPurpose::Symbols, Label, Idx);
+}
+
+static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
+ uint32_t Modi) {
+ return StreamInfo::createModuleStream(Label, StreamIdx, Modi);
+}
+
+struct IndexedModuleDescriptor {
+ uint32_t Modi;
+ DbiModuleDescriptor Descriptor;
+};
+
+void llvm::pdb::discoverStreamPurposes(PDBFile &File,
+ SmallVectorImpl<StreamInfo> &Streams) {
// It's OK if we fail to load some of these streams, we still attempt to print
// what we can.
auto Dbi = File.getPDBDbiStream();
@@ -33,16 +81,18 @@ void llvm::pdb::discoverStreamPurposes(
auto Info = File.getPDBInfoStream();
uint32_t StreamCount = File.getNumStreams();
- DenseMap<uint16_t, DbiModuleDescriptor> ModStreams;
+ DenseMap<uint16_t, IndexedModuleDescriptor> ModStreams;
DenseMap<uint16_t, std::string> NamedStreams;
if (Dbi) {
const DbiModuleList &Modules = Dbi->modules();
for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
- DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I);
- uint16_t SN = Descriptor.getModuleStreamIndex();
+ IndexedModuleDescriptor IMD;
+ IMD.Modi = I;
+ IMD.Descriptor = Modules.getModuleDescriptor(I);
+ uint16_t SN = IMD.Descriptor.getModuleStreamIndex();
if (SN != kInvalidStreamIndex)
- ModStreams[SN] = Descriptor;
+ ModStreams[SN] = IMD;
}
}
if (Info) {
@@ -52,77 +102,76 @@ void llvm::pdb::discoverStreamPurposes(
}
}
- Purposes.resize(StreamCount);
+ Streams.resize(StreamCount);
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- std::pair<StreamPurpose, std::string> Value;
if (StreamIdx == OldMSFDirectory)
- Value = std::make_pair(StreamPurpose::Other, "Old MSF Directory");
+ Streams[StreamIdx] = otherStream("Old MSF Directory", StreamIdx);
else if (StreamIdx == StreamPDB)
- Value = std::make_pair(StreamPurpose::Other, "PDB Stream");
+ Streams[StreamIdx] = otherStream("PDB Stream", StreamIdx);
else if (StreamIdx == StreamDBI)
- Value = std::make_pair(StreamPurpose::Other, "DBI Stream");
+ Streams[StreamIdx] = otherStream("DBI Stream", StreamIdx);
else if (StreamIdx == StreamTPI)
- Value = std::make_pair(StreamPurpose::Other, "TPI Stream");
+ Streams[StreamIdx] = otherStream("TPI Stream", StreamIdx);
else if (StreamIdx == StreamIPI)
- Value = std::make_pair(StreamPurpose::Other, "IPI Stream");
+ Streams[StreamIdx] = otherStream("IPI Stream", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
- Value = std::make_pair(StreamPurpose::Other, "Global Symbol Hash");
+ Streams[StreamIdx] = otherStream("Global Symbol Hash", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
- Value = std::make_pair(StreamPurpose::Other, "Public Symbol Hash");
+ Streams[StreamIdx] = otherStream("Public Symbol Hash", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
- Value = std::make_pair(StreamPurpose::Other, "Public Symbol Records");
+ Streams[StreamIdx] = symbolStream("Symbol Records", StreamIdx);
else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
- Value = std::make_pair(StreamPurpose::Other, "TPI Hash");
+ Streams[StreamIdx] = otherStream("TPI Hash", StreamIdx);
else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
- Value = std::make_pair(StreamPurpose::Other, "TPI Aux Hash");
+ Streams[StreamIdx] = otherStream("TPI Aux Hash", StreamIdx);
else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
- Value = std::make_pair(StreamPurpose::Other, "IPI Hash");
+ Streams[StreamIdx] = otherStream("IPI Hash", StreamIdx);
else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
- Value = std::make_pair(StreamPurpose::Other, "IPI Aux Hash");
+ Streams[StreamIdx] = otherStream("IPI Aux Hash", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
- Value = std::make_pair(StreamPurpose::Other, "Exception Data");
+ Streams[StreamIdx] = otherStream("Exception Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
- Value = std::make_pair(StreamPurpose::Other, "Fixup Data");
+ Streams[StreamIdx] = otherStream("Fixup Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
- Value = std::make_pair(StreamPurpose::Other, "FPO Data");
+ Streams[StreamIdx] = otherStream("FPO Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
- Value = std::make_pair(StreamPurpose::Other, "New FPO Data");
+ Streams[StreamIdx] = otherStream("New FPO Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
- Value = std::make_pair(StreamPurpose::Other, "Omap From Source Data");
+ Streams[StreamIdx] = otherStream("Omap From Source Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
- Value = std::make_pair(StreamPurpose::Other, "Omap To Source Data");
+ Streams[StreamIdx] = otherStream("Omap To Source Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
- Value = std::make_pair(StreamPurpose::Other, "Pdata");
+ Streams[StreamIdx] = otherStream("Pdata", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
- Value = std::make_pair(StreamPurpose::Other, "Section Header Data");
+ Streams[StreamIdx] = otherStream("Section Header Data", StreamIdx);
else if (Dbi &&
StreamIdx ==
Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
- Value =
- std::make_pair(StreamPurpose::Other, "Section Header Original Data");
+ Streams[StreamIdx] =
+ otherStream("Section Header Original Data", StreamIdx);
else if (Dbi &&
StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
- Value = std::make_pair(StreamPurpose::Other, "Token Rid Data");
+ Streams[StreamIdx] = otherStream("Token Rid Data", StreamIdx);
else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
- Value = std::make_pair(StreamPurpose::Other, "Xdata");
+ Streams[StreamIdx] = otherStream("Xdata", StreamIdx);
else {
auto ModIter = ModStreams.find(StreamIdx);
auto NSIter = NamedStreams.find(StreamIdx);
if (ModIter != ModStreams.end()) {
- Value = std::make_pair(StreamPurpose::ModuleStream,
- ModIter->second.getModuleName());
+ Streams[StreamIdx] =
+ moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
+ ModIter->second.Modi);
} else if (NSIter != NamedStreams.end()) {
- Value = std::make_pair(StreamPurpose::NamedStream, NSIter->second);
+ Streams[StreamIdx] = namedStream(NSIter->second, StreamIdx);
} else {
- Value = std::make_pair(StreamPurpose::Other, "???");
+ Streams[StreamIdx] = otherStream("???", StreamIdx);
}
}
- Purposes[StreamIdx] = Value;
}
// Consume errors from missing streams.
@@ -135,18 +184,3 @@ void llvm::pdb::discoverStreamPurposes(
if (!Info)
consumeError(Info.takeError());
}
-
-void llvm::pdb::discoverStreamPurposes(PDBFile &File,
- SmallVectorImpl<std::string> &Purposes) {
- SmallVector<std::pair<StreamPurpose, std::string>, 24> SP;
- discoverStreamPurposes(File, SP);
- Purposes.reserve(SP.size());
- for (const auto &P : SP) {
- if (P.first == StreamPurpose::NamedStream)
- Purposes.push_back(formatv("Named Stream \"{0}\"", P.second));
- else if (P.first == StreamPurpose::ModuleStream)
- Purposes.push_back(formatv("Module \"{0}\"", P.second));
- else
- Purposes.push_back(P.second);
- }
-}
diff --git a/llvm/tools/llvm-pdbutil/StreamUtil.h b/llvm/tools/llvm-pdbutil/StreamUtil.h
index f49c0a0eceb..443267ca329 100644
--- a/llvm/tools/llvm-pdbutil/StreamUtil.h
+++ b/llvm/tools/llvm-pdbutil/StreamUtil.h
@@ -10,20 +10,41 @@
#ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <string>
namespace llvm {
namespace pdb {
class PDBFile;
-enum class StreamPurpose { NamedStream, ModuleStream, Other };
+enum class StreamPurpose { NamedStream, ModuleStream, Symbols, Other };
+
+struct StreamInfo {
+public:
+ StreamInfo() {}
+
+ uint32_t getModuleIndex() const { return *ModuleIndex; }
+ StreamPurpose getPurpose() const { return Purpose; }
+ StringRef getShortName() const { return Name; }
+ uint32_t getStreamIndex() const { return StreamIndex; }
+ std::string getLongName() const;
+
+ static StreamInfo createStream(StreamPurpose Purpose, StringRef Name,
+ uint32_t StreamIndex);
+ static StreamInfo createModuleStream(StringRef Module, uint32_t StreamIndex,
+ uint32_t Modi);
+
+private:
+ StreamPurpose Purpose;
+ uint32_t StreamIndex;
+ std::string Name;
+ Optional<uint32_t> ModuleIndex;
+};
void discoverStreamPurposes(PDBFile &File,
- SmallVectorImpl<std::string> &Purposes);
-void discoverStreamPurposes(
- PDBFile &File,
- SmallVectorImpl<std::pair<StreamPurpose, std::string>> &Purposes);
+ SmallVectorImpl<StreamInfo> &Streams);
}
}
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 75560b3f937..045eb71a209 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -29,6 +29,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
@@ -70,6 +71,7 @@
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/LineIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -80,6 +82,8 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
+#include <set>
+
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::msf;
@@ -418,6 +422,10 @@ cl::opt<bool> DumpStreamBlocks(
"stream-blocks",
cl::desc("Add block information to the output of -streams"),
cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+ DumpModuleStats("mod-stats",
+ cl::desc("Dump a detailed size breakdown for each module"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
// TYPE OPTIONS
cl::opt<bool> DumpTypes("types",
@@ -507,6 +515,10 @@ cl::opt<uint32_t> DumpModi("modi", cl::Optional,
cl::desc("For all options that iterate over "
"modules, limit to the specified module"),
cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> JustMyCode("jmc", cl::Optional,
+ cl::desc("For all options that iterate over modules, "
+ "ignore modules from system libraries"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
// MISCELLANEOUS OPTIONS
cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
index 621c9fad437..901d2a8cd61 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -127,6 +127,7 @@ namespace dump {
extern llvm::cl::opt<bool> DumpSummary;
extern llvm::cl::opt<bool> DumpFpm;
extern llvm::cl::opt<bool> DumpStreams;
+extern llvm::cl::opt<bool> DumpModuleStats;
extern llvm::cl::opt<bool> DumpStreamBlocks;
extern llvm::cl::opt<bool> DumpLines;
@@ -146,6 +147,7 @@ extern llvm::cl::opt<bool> DumpIdData;
extern llvm::cl::opt<bool> DumpIdExtras;
extern llvm::cl::list<uint32_t> DumpIdIndex;
extern llvm::cl::opt<uint32_t> DumpModi;
+extern llvm::cl::opt<bool> JustMyCode;
extern llvm::cl::opt<bool> DumpSymbols;
extern llvm::cl::opt<bool> DumpSymRecordBytes;
extern llvm::cl::opt<bool> DumpGlobals;
OpenPOWER on IntegriCloud