summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbutil
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-pdbutil')
-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