[llvm-pdbdump] Rework command line options.
When dumping huge PDB files, too many of the options were grouped
together so you would get neverending spew of output. This patch
introduces more granular display options so you can only dump the
fields you actually care about.
llvm-svn: 270607
diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
index 4d7941a..1ff5c3f 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
@@ -34,6 +34,7 @@
PdbRaw_DbiVer getDbiVersion() const;
uint32_t getAge() const;
uint16_t getPublicSymbolStreamIndex() const;
+ uint16_t getGlobalSymbolStreamIndex() const;
bool isIncrementallyLinked() const;
bool hasCTypes() const;
diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
index 7e1811d..2cc2a73 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
@@ -188,6 +188,10 @@
return Header->PublicSymbolStreamIndex;
}
+uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
+ return Header->GlobalSymbolStreamIndex;
+}
+
bool DbiStream::isIncrementallyLinked() const {
return (Header->Flags & FlagIncrementalMask) != 0;
}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
index af047f73..09d7198 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
@@ -15,8 +15,12 @@
using namespace llvm::pdb;
MappedBlockStream::MappedBlockStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) {
- StreamLength = Pdb.getStreamByteSize(StreamIdx);
- BlockList = Pdb.getStreamBlockList(StreamIdx);
+ if (StreamIdx >= Pdb.getNumStreams()) {
+ StreamLength = 0;
+ } else {
+ StreamLength = Pdb.getStreamByteSize(StreamIdx);
+ BlockList = Pdb.getStreamBlockList(StreamIdx);
+ }
}
Error MappedBlockStream::readBytes(uint32_t Offset,
@@ -54,5 +58,23 @@
Error MappedBlockStream::getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
uint32_t Length) const {
- return make_error<RawError>(raw_error_code::feature_unsupported);
+ uint32_t BlockNum = Offset / Pdb.getBlockSize();
+ uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
+ uint32_t BytesAvailableInBlock = Pdb.getBlockSize() - OffsetInBlock;
+
+ // If this is the last block in the stream, not all of the data is valid.
+ if (BlockNum == BlockList.size() - 1) {
+ uint32_t AllocatedBytesInBlock = StreamLength % Pdb.getBlockSize();
+ if (AllocatedBytesInBlock < BytesAvailableInBlock)
+ BytesAvailableInBlock = AllocatedBytesInBlock;
+ }
+ if (BytesAvailableInBlock < Length)
+ return make_error<RawError>(raw_error_code::feature_unsupported);
+
+ uint32_t StreamBlockAddr = BlockList[BlockNum];
+ StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
+ Data = Data.substr(OffsetInBlock, Length);
+
+ Buffer = ArrayRef<uint8_t>(Data.bytes_begin(), Data.bytes_end());
+ return Error::success();
}
diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test
index bb59135..8f1ff2d 100644
--- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test
+++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test
@@ -1,7 +1,9 @@
-; RUN: llvm-pdbdump --dump-headers -dump-tpi-records -dump-tpi-record-bytes -dump-module-syms \
-; RUN: -dump-sym-record-bytes --dump-publics %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
-; RUN: llvm-pdbdump --dump-headers %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
-; RUN: llvm-pdbdump --dump-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
+; RUN: llvm-pdbdump -raw-headers -raw-tpi-records -raw-tpi-record-bytes -raw-module-syms \
+; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \
+; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
+; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \
+; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
+; RUN: llvm-pdbdump -raw-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
; EMPTY: FileHeaders {
; EMPTY-NEXT: BlockSize: 4096
@@ -105,6 +107,8 @@
; EMPTY-NEXT: Is Stripped: No
; EMPTY-NEXT: Machine Type: x86
; EMPTY-NEXT: Symbol Record Stream Index: 8
+; EMPTY-NEXT: Public Symbol Stream Index: 7
+; EMPTY-NEXT: Global Symbol Stream Index: 6
; EMPTY-NEXT: Toolchain Version: 12.0
; EMPTY-NEXT: mspdb120.dll version: 12.0.31101
; EMPTY-NEXT: Modules [
@@ -525,6 +529,8 @@
; BIG-NEXT: Is Stripped: No
; BIG-NEXT: Machine Type: x86
; BIG-NEXT: Symbol Record Stream Index: 9
+; BIG-NEXT: Public Symbol Stream Index: 8
+; BIG-NEXT: Global Symbol Stream Index: 7
; BIG-NEXT: Toolchain Version: 14.0
; BIG-NEXT: mspdb140.dll version: 14.0.23918
; BIG-NEXT: Modules [
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index d8dcd3d..0946873 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -104,31 +104,38 @@
cl::desc("Assume the module is loaded at the specified address"),
cl::cat(OtherOptions));
-cl::opt<bool> DumpHeaders("dump-headers", cl::desc("dump PDB headers"),
+cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
cl::cat(NativeOtions));
-cl::opt<bool> DumpStreamSizes("dump-stream-sizes",
+cl::opt<bool> DumpStreamSizes("raw-stream-sizes",
cl::desc("dump PDB stream sizes"),
cl::cat(NativeOtions));
-cl::opt<bool> DumpStreamBlocks("dump-stream-blocks",
+cl::opt<bool> DumpStreamBlocks("raw-stream-blocks",
cl::desc("dump PDB stream blocks"),
cl::cat(NativeOtions));
-cl::opt<bool> DumpTpiRecords("dump-tpi-records",
+cl::opt<bool> DumpTpiRecords("raw-tpi-records",
cl::desc("dump CodeView type records"),
cl::cat(NativeOtions));
cl::opt<bool>
- DumpTpiRecordBytes("dump-tpi-record-bytes",
+ DumpTpiRecordBytes("raw-tpi-record-bytes",
cl::desc("dump CodeView type record raw bytes"),
cl::cat(NativeOtions));
-cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"),
- cl::cat(NativeOtions));
-cl::opt<bool> DumpModuleSyms("dump-module-syms",
- cl::desc("dump module symbols"),
+cl::opt<std::string> DumpStreamDataIdx("raw-stream",
+ cl::desc("dump stream data"),
+ cl::cat(NativeOtions));
+cl::opt<std::string> DumpStreamDataName("raw-stream-name",
+ cl::desc("dump stream data"),
+ cl::cat(NativeOtions));
+cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"),
+ cl::cat(NativeOtions));
+cl::opt<bool> DumpModuleFiles("raw-module-files",
+ cl::desc("dump file information"),
+ cl::cat(NativeOtions));
+cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"),
cl::cat(NativeOtions));
-cl::opt<bool> DumpPublics("dump-publics",
- cl::desc("dump Publics stream data"),
+cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"),
cl::cat(NativeOtions));
cl::opt<bool>
- DumpSymRecordBytes("dump-sym-record-bytes",
+ DumpSymRecordBytes("raw-sym-record-bytes",
cl::desc("dump CodeView symbol record raw bytes"),
cl::cat(NativeOtions));
@@ -227,28 +234,22 @@
static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
uint32_t StreamCount = File.getNumStreams();
- StringRef DumpStreamStr = opts::DumpStreamData;
+ StringRef DumpStreamStr = opts::DumpStreamDataIdx;
uint32_t DumpStreamNum;
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
DumpStreamNum >= StreamCount)
return Error::success();
- uint32_t StreamBytesRead = 0;
- uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum);
- auto StreamBlocks = File.getStreamBlockList(DumpStreamNum);
-
- for (uint32_t StreamBlockAddr : StreamBlocks) {
- uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead;
- if (BytesLeftToReadInStream == 0)
- break;
-
+ MappedBlockStream S(DumpStreamNum, File);
+ StreamReader R(S);
+ while (R.bytesRemaining() > 0) {
+ ArrayRef<uint8_t> Data;
uint32_t BytesToReadInBlock = std::min(
- BytesLeftToReadInStream, static_cast<uint32_t>(File.getBlockSize()));
- auto StreamBlockData =
- File.getBlockData(StreamBlockAddr, BytesToReadInBlock);
-
- outs() << StreamBlockData;
- StreamBytesRead += StreamBlockData.size();
+ R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
+ if (auto EC = R.getArrayRef(Data, BytesToReadInBlock))
+ return EC;
+ outs() << StringRef(reinterpret_cast<const char *>(Data.begin()),
+ Data.size());
}
return Error::success();
}
@@ -268,18 +269,20 @@
return Error::success();
}
-static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File,
- StringRef Stream) {
+static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File) {
+ if (opts::DumpStreamDataName.empty())
+ return Error::success();
+
auto InfoS = File.getPDBInfoStream();
if (auto EC = InfoS.takeError())
return EC;
InfoStream &IS = InfoS.get();
- uint32_t NameStreamIndex = IS.getNamedStreamIndex(Stream);
+ uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName);
if (NameStreamIndex != 0) {
std::string Name("Stream '");
- Name += Stream;
+ Name += opts::DumpStreamDataName;
Name += "'";
DictScope D(P, Name);
P.printNumber("Index", NameStreamIndex);
@@ -319,6 +322,8 @@
P.printBoolean("Is Stripped", DS.isStripped());
P.printObject("Machine Type", DS.getMachineType());
P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex());
+ P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex());
+ P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex());
uint16_t Major = DS.getBuildMajorVersion();
uint16_t Minor = DS.getBuildMinorVersion();
@@ -330,42 +335,48 @@
DllStream.flush();
P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
- ListScope L(P, "Modules");
- for (auto &Modi : DS.modules()) {
- DictScope DD(P);
- P.printString("Name", Modi.Info.getModuleName());
- P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
- P.printString("Object File Name", Modi.Info.getObjFileName());
- P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
- P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
- P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
- P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
- P.printNumber("C13 Line Info Byte Size",
- Modi.Info.getC13LineInfoByteSize());
- P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
- P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
- P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
- {
- std::string FileListName =
- to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
- ListScope LL(P, FileListName);
- for (auto File : Modi.SourceFiles)
- P.printString(File);
- }
- if (opts::DumpModuleSyms || opts::DumpSymRecordBytes) {
- ListScope SS(P, "Symbols");
- ModStream ModS(File, Modi.Info);
- if (auto EC = ModS.reload())
- return EC;
+ if (opts::DumpModules || opts::DumpModuleSyms || opts::DumpModuleFiles) {
+ ListScope L(P, "Modules");
+ for (auto &Modi : DS.modules()) {
+ DictScope DD(P);
+ P.printString("Name", Modi.Info.getModuleName());
+ P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
+ P.printString("Object File Name", Modi.Info.getObjFileName());
+ P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
+ P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
+ P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
+ P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
+ P.printNumber("C13 Line Info Byte Size",
+ Modi.Info.getC13LineInfoByteSize());
+ P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
+ P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
+ P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
+ if (opts::DumpModuleFiles) {
+ std::string FileListName =
+ to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
+ ListScope LL(P, FileListName);
+ for (auto File : Modi.SourceFiles)
+ P.printString(File);
+ }
+ bool HasModuleDI =
+ (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
+ bool ShouldDumpSymbols =
+ (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
+ if (HasModuleDI && ShouldDumpSymbols) {
+ ListScope SS(P, "Symbols");
+ ModStream ModS(File, Modi.Info);
+ if (auto EC = ModS.reload())
+ return EC;
- codeview::CVSymbolDumper SD(P, TD, nullptr, false);
- for (auto &S : ModS.symbols()) {
- DictScope DD(P, "");
+ codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+ for (auto &S : ModS.symbols()) {
+ DictScope DD(P, "");
- if (opts::DumpModuleSyms)
- SD.dump(S);
- if (opts::DumpSymRecordBytes)
- P.printBinaryBlock("Bytes", S.Data);
+ if (opts::DumpModuleSyms)
+ SD.dump(S);
+ if (opts::DumpSymRecordBytes)
+ P.printBinaryBlock("Bytes", S.Data);
+ }
}
}
}
@@ -474,7 +485,7 @@
if (auto EC = dumpInfoStream(P, File))
return EC;
- if (auto EC = dumpNamedStream(P, File, "/names"))
+ if (auto EC = dumpNamedStream(P, File))
return EC;
codeview::CVTypeDumper TD(P, false);
@@ -486,12 +497,40 @@
if (auto EC = dumpPublicsStream(P, File, TD))
return EC;
-return Error::success();
+ return Error::success();
+}
+
+bool isRawDumpEnabled() {
+ if (opts::DumpHeaders)
+ return true;
+ if (opts::DumpModules)
+ return true;
+ if (opts::DumpModuleFiles)
+ return true;
+ if (opts::DumpModuleSyms)
+ return true;
+ if (!opts::DumpStreamDataIdx.empty())
+ return true;
+ if (!opts::DumpStreamDataName.empty())
+ return true;
+ if (opts::DumpPublics)
+ return true;
+ if (opts::DumpStreamBlocks)
+ return true;
+ if (opts::DumpStreamSizes)
+ return true;
+ if (opts::DumpSymRecordBytes)
+ return true;
+ if (opts::DumpTpiRecordBytes)
+ return true;
+ if (opts::DumpTpiRecords)
+ return true;
+ return false;
}
static void dumpInput(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- if (opts::DumpHeaders || !opts::DumpStreamData.empty()) {
+ if (isRawDumpEnabled()) {
auto E = loadDataForPDB(PDB_ReaderType::Raw, Path, Session);
if (!E) {
RawSession *RS = static_cast<RawSession *>(Session.get());