Skip to content

Commit

Permalink
[llvm-pdbdump] Rework command line options.
Browse files Browse the repository at this point in the history
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270607 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Zachary Turner committed May 24, 2016
1 parent 0658e94 commit 45ab259
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 78 deletions.
1 change: 1 addition & 0 deletions include/llvm/DebugInfo/PDB/Raw/DbiStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class DbiStream {
PdbRaw_DbiVer getDbiVersion() const;
uint32_t getAge() const;
uint16_t getPublicSymbolStreamIndex() const;
uint16_t getGlobalSymbolStreamIndex() const;

bool isIncrementallyLinked() const;
bool hasCTypes() const;
Expand Down
4 changes: 4 additions & 0 deletions lib/DebugInfo/PDB/Raw/DbiStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ uint16_t DbiStream::getPublicSymbolStreamIndex() const {
return Header->PublicSymbolStreamIndex;
}

uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
return Header->GlobalSymbolStreamIndex;
}

bool DbiStream::isIncrementallyLinked() const {
return (Header->Flags & FlagIncrementalMask) != 0;
}
Expand Down
28 changes: 25 additions & 3 deletions lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ using namespace llvm;
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,
Expand Down Expand Up @@ -54,5 +58,23 @@ Error MappedBlockStream::readBytes(uint32_t Offset,

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();
}
14 changes: 10 additions & 4 deletions test/DebugInfo/PDB/pdbdump-headers.test
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 [
Expand Down Expand Up @@ -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 [
Expand Down
181 changes: 110 additions & 71 deletions tools/llvm-pdbdump/llvm-pdbdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,31 +104,38 @@ cl::opt<uint64_t> LoadAddress(
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));

Expand Down Expand Up @@ -227,28 +234,22 @@ static Error dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {

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();
}
Expand All @@ -268,18 +269,20 @@ static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
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);
Expand Down Expand Up @@ -319,6 +322,8 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
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();
Expand All @@ -330,42 +335,48 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
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;

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::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, "");

if (opts::DumpModuleSyms)
SD.dump(S);
if (opts::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
}
}
}
Expand Down Expand Up @@ -474,7 +485,7 @@ static Error dumpStructure(RawSession &RS) {
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);
Expand All @@ -486,12 +497,40 @@ static Error dumpStructure(RawSession &RS) {

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());
Expand Down

0 comments on commit 45ab259

Please sign in to comment.