[pdb] Add command line options for dumping individual streams and blocks

I ran into a situation where I wanted to print out the contents of
page 6 of a PDB as a binary blob, and there was no straightforward
way to do that.

In addition to adding that, this patch also adds the ability to dump
a stream by index as a binary blob, and it will stitch together all
the blocks and dump the whole thing as one seemingly contiguous
sequence of bytes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281070 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2016-09-09 18:17:52 +00:00
parent 8b2faaa82b
commit 892ff5d6d9
7 changed files with 148 additions and 193 deletions

View File

@ -1,10 +1,10 @@
; RUN: llvm-pdbdump raw -headers -tpi-records -tpi-record-bytes -module-syms \ ; RUN: llvm-pdbdump raw -headers -tpi-records -tpi-record-bytes -module-syms \
; RUN: -sym-record-bytes -publics -module-files -stream-name=/names \ ; RUN: -sym-record-bytes -publics -module-files \
; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \ ; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \
; RUN: -section-contribs -section-map -section-headers -line-info \ ; RUN: -section-contribs -section-map -section-headers -line-info \
; RUN: -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s ; RUN: -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
; RUN: llvm-pdbdump raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s ; RUN: llvm-pdbdump raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
; RUN: llvm-pdbdump raw -headers -stream-name=/names -modules -module-files \ ; RUN: llvm-pdbdump raw -headers -modules -module-files \
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
; RUN: not llvm-pdbdump raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s ; RUN: not llvm-pdbdump raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
@ -67,17 +67,6 @@
; EMPTY-NEXT: Age: 1 ; EMPTY-NEXT: Age: 1
; EMPTY-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0} ; EMPTY-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
; EMPTY-NEXT: } ; EMPTY-NEXT: }
; EMPTY-NEXT: Stream '/names' {
; EMPTY-NEXT: Index: 13
; EMPTY-NEXT: Signature: 0xEFFEEFFE
; EMPTY-NEXT: Version: 1
; EMPTY-NEXT: Name Count: 4
; EMPTY-NEXT: Names [
; EMPTY-NEXT: 1: d:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)
; EMPTY-NEXT: 86: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
; EMPTY-NEXT: 134: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =
; EMPTY-NEXT: ]
; EMPTY-NEXT: }
; EMPTY-NEXT: Type Info Stream (TPI) { ; EMPTY-NEXT: Type Info Stream (TPI) {
; EMPTY-NEXT: TPI Version: 20040203 ; EMPTY-NEXT: TPI Version: 20040203
; EMPTY-NEXT: Record count: 75 ; EMPTY-NEXT: Record count: 75
@ -1688,105 +1677,6 @@
; BIG-NEXT: Age: 1 ; BIG-NEXT: Age: 1
; BIG-NEXT: Guid: {880ECC89-DF81-0B4F-839C-58CBD052E937} ; BIG-NEXT: Guid: {880ECC89-DF81-0B4F-839C-58CBD052E937}
; BIG-NEXT: } ; BIG-NEXT: }
; BIG-NEXT: Stream '/names' {
; BIG-NEXT: Index: 13
; BIG-NEXT: Signature: 0xEFFEEFFE
; BIG-NEXT: Version: 1
; BIG-NEXT: Name Count: 92
; BIG-NEXT: Names [
; BIG-NEXT: 2938: f:\dd\vctools\crt\vcruntime\inc\vcruntime_startup.h
; BIG-NEXT: 2569: f:\dd\vctools\crt\vcstartup\src\misc\checkcfg.c
; BIG-NEXT: 261: f:\dd\vctools\langapi\include\isa_availability.h
; BIG-NEXT: 4526: $T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = $esp $T1 4 + =
; BIG-NEXT: 4129: f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl
; BIG-NEXT: 4415: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 40 - ^ = $23 $T0 44 - ^ = $24 $T0 48 - ^ =
; BIG-NEXT: 4921: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $23 $T0 16 - ^ = $24 $T0 20 - ^ =
; BIG-NEXT: 310: f:\dd\externalapis\windows\8.1\sdk\inc\wingdi.h
; BIG-NEXT: 3880: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\predefined c++ types (compiler internal)
; BIG-NEXT: 2401: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $23 $T0 24 - ^ =
; BIG-NEXT: 635: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
; BIG-NEXT: 5014: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_stubs.cpp
; BIG-NEXT: 157: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =
; BIG-NEXT: 2766: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_init.c
; BIG-NEXT: 3196: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h
; BIG-NEXT: 4274: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $23 $T0 4 - ^ =
; BIG-NEXT: 5322: f:\dd\vctools\crt\vcstartup\src\defaults\default_precision.cpp
; BIG-NEXT: 3768: f:\dd\vctools\crt\vcstartup\src\defaults\thread_locale.cpp
; BIG-NEXT: 592: f:\dd\externalapis\unifiedcrt\inc\string.h
; BIG-NEXT: 887: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
; BIG-NEXT: 1898: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $20 $T0 4 - ^ = $23 $T0 8 - ^ =
; BIG-NEXT: 1: d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\test.cpp
; BIG-NEXT: 3362: f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h
; BIG-NEXT: 1692: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
; BIG-NEXT: 4077: f:\dd\externalapis\unifiedcrt\inc\corecrt_startup.h
; BIG-NEXT: 5108: f:\dd\externalapis\windows\8.1\sdk\inc\processthreadsapi.h
; BIG-NEXT: 2353: f:\dd\vctools\crt\vcstartup\src\gs\gs_support.c
; BIG-NEXT: 5167: f:\dd\vctools\crt\vcstartup\src\utility\utility_desktop.cpp
; BIG-NEXT: 2881: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_detection.c
; BIG-NEXT: 3714: f:\dd\vctools\crt\vcstartup\src\defaults\new_mode.cpp
; BIG-NEXT: 2206: f:\dd\vctools\crt\vcstartup\src\eh\i386\secchk.c
; BIG-NEXT: 3661: f:\dd\vctools\crt\vcstartup\src\defaults\matherr.cpp
; BIG-NEXT: 457: f:\dd\externalapis\unifiedcrt\inc\corecrt.h
; BIG-NEXT: 3481: f:\dd\vctools\crt\vcstartup\src\defaults\env_mode.cpp
; BIG-NEXT: 992: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
; BIG-NEXT: 1791: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =
; BIG-NEXT: 4028: f:\dd\vctools\crt\vcstartup\src\eh\tncleanup.cpp
; BIG-NEXT: 1977: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $20 $T0 4 - ^ = $23 $T0 8 - ^ = $24 $T0 12 - ^ =
; BIG-NEXT: 688: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
; BIG-NEXT: 2074: f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm
; BIG-NEXT: 214: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
; BIG-NEXT: 939: f:\dd\vctools\crt\vcstartup\src\misc\i386\cpu_disp.c
; BIG-NEXT: 2617: f:\dd\vctools\crt\vcstartup\src\misc\guard_support.c
; BIG-NEXT: 3827: f:\dd\vctools\crt\vcruntime\inc\vcruntime_typeinfo.h
; BIG-NEXT: 407: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
; BIG-NEXT: 2476: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $23 $T0 24 - ^ = $24 $T0 28 - ^ =
; BIG-NEXT: 4609: f:\dd\vctools\crt\vcstartup\src\utility\utility.cpp
; BIG-NEXT: 4184: f:\dd\vctools\crt\vcruntime\inc\eh.h
; BIG-NEXT: 5227: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 808 - ^ = $23 $T0 812 - ^ =
; BIG-NEXT: 1403: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\predefined c++ attributes (compiler internal)
; BIG-NEXT: 60: d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\predefined c++ attributes (compiler internal)
; BIG-NEXT: 2990: f:\dd\vctools\crt\vcstartup\src\defaults\argv_mode.cpp
; BIG-NEXT: 3045: f:\dd\vctools\crt\vcstartup\src\defaults\commit_mode.cpp
; BIG-NEXT: 4221: f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp
; BIG-NEXT: 3320: f:\dd\externalapis\unifiedcrt\inc\stdio.h
; BIG-NEXT: 3974: f:\dd\vctools\crt\vcruntime\inc\vcruntime_exception.h
; BIG-NEXT: 1551: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
; BIG-NEXT: 2711: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_dtor.c
; BIG-NEXT: 501: f:\dd\vctools\crt\vcruntime\inc\i386\mmintrin.h
; BIG-NEXT: 4661: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $23 $T0 4 - ^ =
; BIG-NEXT: 4735: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 28 - ^ = $23 $T0 32 - ^ = $24 $T0 36 - ^ =
; BIG-NEXT: 358: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
; BIG-NEXT: 1362: f:\dd\vctools\crt\vcruntime\inc\rtcapi.h
; BIG-NEXT: 3419: f:\dd\vctools\crt\vcstartup\src\defaults\denormal_control.cpp
; BIG-NEXT: 2255: f:\dd\vctools\crt\vcstartup\src\gs\gs_report.c
; BIG-NEXT: 2302: f:\dd\externalapis\windows\8.1\sdk\inc\minwindef.h
; BIG-NEXT: 3102: f:\dd\vctools\crt\vcruntime\inc\vadefs.h
; BIG-NEXT: 2128: _TP_CALLBACK_ENVIRON_V3
; BIG-NEXT: 4336: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $23 $T0 4 - ^ = $24 $T0 8 - ^ =
; BIG-NEXT: 3143: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
; BIG-NEXT: 1643: f:\dd\vctools\crt\vcstartup\src\rtc\initsect.cpp
; BIG-NEXT: 1041: f:\dd\externalapis\unifiedcrt\inc\ctype.h
; BIG-NEXT: 2821: f:\dd\vctools\crt\vcstartup\src\utility\matherr_detection.c
; BIG-NEXT: 3590: f:\dd\vctools\crt\vcstartup\src\defaults\invalid_parameter_handler.cpp
; BIG-NEXT: 788: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
; BIG-NEXT: 2152: f:\dd\vctools\crt\vcstartup\src\eh\i386\chandler4gs.c
; BIG-NEXT: 5069: f:\dd\vctools\langapi\include\ehdata.h
; BIG-NEXT: 3535: f:\dd\vctools\crt\vcstartup\src\defaults\file_mode.cpp
; BIG-NEXT: 2670: f:\dd\externalapis\unifiedcrt\inc\math.h
; BIG-NEXT: 1502: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
; BIG-NEXT: 1158: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 48 - ^ = $23 $T0 52 - ^ =
; BIG-NEXT: 1251: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 48 - ^ = $23 $T0 52 - ^ = $24 $T0 56 - ^ =
; BIG-NEXT: 1600: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
; BIG-NEXT: 3247: f:\dd\vctools\crt\vcstartup\src\defaults\default_local_stdio_options.cpp
; BIG-NEXT: 738: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
; BIG-NEXT: 549: f:\dd\externalapis\unifiedcrt\inc\malloc.h
; BIG-NEXT: 837: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
; BIG-NEXT: 1836: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $20 $T0 4 - ^ =
; BIG-NEXT: 1083: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $20 $T0 48 - ^ =
; BIG-NEXT: 4846: $T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $23 $T0 16 - ^ =
; BIG-NEXT: 1740: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
; BIG-NEXT: ]
; BIG-NEXT: }
; BIG-NEXT: DBI Stream { ; BIG-NEXT: DBI Stream {
; BIG-NEXT: Dbi Version: 19990903 ; BIG-NEXT: Dbi Version: 19990903
; BIG-NEXT: Age: 1 ; BIG-NEXT: Age: 1

View File

@ -0,0 +1,35 @@
; RUN: llvm-pdbdump raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
; RUN: llvm-pdbdump raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
; RUN: not llvm-pdbdump raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
; RUN: not llvm-pdbdump raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
; RUN: not llvm-pdbdump raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
BLOCK0: Block Data {
BLOCK0-NEXT: Block 0 (
BLOCK0-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ |
BLOCK0-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...|
BLOCK0-NEXT: 0020: 00100000 02000000 19000000 88000000 |................|
BLOCK0-NEXT: 0030: 00000000 18000000 00000000 00000000 |................|
BLOCK0: 0FE0: 00000000 00000000 00000000 00000000 |................|
BLOCK0-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................|
BLOCK0-NEXT: )
BLOCK0-NEXT: }
BLOCK01: Block Data {
BLOCK01-NEXT: Block 0 (
BLOCK01-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ |
BLOCK01-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...|
BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 |................|
BLOCK01-NEXT: 0030: 00000000 18000000 00000000 00000000 |................|
BLOCK01: 0FE0: 00000000 00000000 00000000 00000000 |................|
BLOCK01-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................|
BLOCK01-NEXT: )
BLOCK01-NEXT: Block 1 (
BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
BLOCK01-NEXT: 0010: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
BLOCK01: 0FE0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
BLOCK01-NEXT: 0FF0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
BLOCK01-NEXT: )
BLOCK01-NEXT: }
BADSYNTAX: Argument '{{.*}}' invalid format.

View File

@ -0,0 +1,17 @@
; RUN: llvm-pdbdump raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
; RUN: not llvm-pdbdump raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
STREAM1: Stream Data {
STREAM1-NEXT: Stream 1 (
STREAM1-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 |..1....T.....5VA|
STREAM1-NEXT: 0010: 86A0A249 896F9988 FAE52FF0 22000000 |...I.o..../."...|
STREAM1-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 |/LinkInfo./names|
STREAM1-NEXT: 0030: 002F7372 632F6865 61646572 626C6F63 |./src/headerbloc|
STREAM1-NEXT: 0040: 6B000300 00000600 00000100 00001A00 |k...............|
STREAM1-NEXT: 0050: 00000000 00001100 00000900 00000A00 |................|
STREAM1-NEXT: 0060: 00000D00 00000000 00000500 00000000 |................|
STREAM1-NEXT: 0070: 00004191 3201 |..A.2.|
STREAM1-NEXT: )
STREAM1-NEXT: }
INVALIDSTREAM: Native PDB Error: The specified stream could not be loaded.

View File

@ -98,15 +98,15 @@ Error LLVMOutputStyle::dump() {
if (auto EC = dumpStreamBlocks()) if (auto EC = dumpStreamBlocks())
return EC; return EC;
if (auto EC = dumpStreamData()) if (auto EC = dumpBlockRanges())
return EC;
if (auto EC = dumpStreamBytes())
return EC; return EC;
if (auto EC = dumpInfoStream()) if (auto EC = dumpInfoStream())
return EC; return EC;
if (auto EC = dumpNamedStream())
return EC;
if (auto EC = dumpTpiStream(StreamTPI)) if (auto EC = dumpTpiStream(StreamTPI))
return EC; return EC;
@ -343,28 +343,58 @@ Error LLVMOutputStyle::dumpStreamBlocks() {
return Error::success(); return Error::success();
} }
Error LLVMOutputStyle::dumpStreamData() { Error LLVMOutputStyle::dumpBlockRanges() {
uint32_t StreamCount = File.getNumStreams(); if (!opts::raw::DumpBlockRange.hasValue())
StringRef DumpStreamStr = opts::raw::DumpStreamDataIdx; return Error::success();
uint32_t DumpStreamNum; auto &R = *opts::raw::DumpBlockRange;
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum)) uint32_t Max = R.Max.getValueOr(R.Min);
if (Max < R.Min)
return make_error<StringError>(
"Invalid block range specified. Max < Min",
std::make_error_code(std::errc::bad_address));
if (Max >= File.getBlockCount())
return make_error<StringError>(
"Invalid block range specified. Requested block out of bounds",
std::make_error_code(std::errc::bad_address));
DictScope D(P, "Block Data");
for (uint32_t I = R.Min; I <= Max; ++I) {
auto ExpectedData = File.getBlockData(I, File.getBlockSize());
if (!ExpectedData)
return ExpectedData.takeError();
std::string Label;
llvm::raw_string_ostream S(Label);
S << "Block " << I;
S.flush();
P.printBinaryBlock(Label, *ExpectedData);
}
return Error::success();
}
Error LLVMOutputStyle::dumpStreamBytes() {
if (opts::raw::DumpStreamData.empty())
return Error::success(); return Error::success();
if (DumpStreamNum >= StreamCount) DictScope D(P, "Stream Data");
return make_error<RawError>(raw_error_code::no_stream); for (uint32_t SI : opts::raw::DumpStreamData) {
if (SI >= File.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
auto S = MappedBlockStream::createIndexedStream( auto S = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
File.getMsfLayout(), File.getMsfBuffer(), DumpStreamNum); File.getMsfBuffer(), SI);
StreamReader R(*S); if (!S)
while (R.bytesRemaining() > 0) { continue;
ArrayRef<uint8_t> Data; StreamReader R(*S);
uint32_t BytesToReadInBlock = std::min( ArrayRef<uint8_t> StreamData;
R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize())); if (auto EC = R.readBytes(StreamData, S->getLength()))
if (auto EC = R.readBytes(Data, BytesToReadInBlock))
return EC; return EC;
P.printBinaryBlock( std::string Label;
"Data", llvm::raw_string_ostream Stream(Label);
StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size())); Stream << "Stream " << SI;
Stream.flush();
P.printBinaryBlock(Label, StreamData);
} }
return Error::success(); return Error::success();
} }
@ -384,47 +414,6 @@ Error LLVMOutputStyle::dumpInfoStream() {
return Error::success(); return Error::success();
} }
Error LLVMOutputStyle::dumpNamedStream() {
if (opts::raw::DumpStreamDataName.empty())
return Error::success();
auto IS = File.getPDBInfoStream();
if (!IS)
return IS.takeError();
uint32_t NameStreamIndex =
IS->getNamedStreamIndex(opts::raw::DumpStreamDataName);
if (NameStreamIndex == 0 || NameStreamIndex >= File.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
if (NameStreamIndex != 0) {
std::string Name("Stream '");
Name += opts::raw::DumpStreamDataName;
Name += "'";
DictScope D(P, Name);
P.printNumber("Index", NameStreamIndex);
auto NameStream = MappedBlockStream::createIndexedStream(
File.getMsfLayout(), File.getMsfBuffer(), NameStreamIndex);
StreamReader Reader(*NameStream);
NameHashTable NameTable;
if (auto EC = NameTable.load(Reader))
return EC;
P.printHex("Signature", NameTable.getSignature());
P.printNumber("Version", NameTable.getHashVersion());
P.printNumber("Name Count", NameTable.getNameCount());
ListScope L(P, "Names");
for (uint32_t ID : NameTable.name_ids()) {
StringRef Str = NameTable.getStringForID(ID);
if (!Str.empty())
P.printString(to_string(ID), Str);
}
}
return Error::success();
}
static void printTypeIndexOffset(raw_ostream &OS, static void printTypeIndexOffset(raw_ostream &OS,
const TypeIndexOffset &TIOff) { const TypeIndexOffset &TIOff) {
OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}"; OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}";

View File

@ -28,10 +28,10 @@ private:
Error dumpFileHeaders(); Error dumpFileHeaders();
Error dumpStreamSummary(); Error dumpStreamSummary();
Error dumpFreePageMap(); Error dumpFreePageMap();
Error dumpBlockRanges();
Error dumpStreamBytes();
Error dumpStreamBlocks(); Error dumpStreamBlocks();
Error dumpStreamData();
Error dumpInfoStream(); Error dumpInfoStream();
Error dumpNamedStream();
Error dumpTpiStream(uint32_t StreamIdx); Error dumpTpiStream(uint32_t StreamIdx);
Error dumpDbiStream(); Error dumpDbiStream();
Error dumpSectionContribs(); Error dumpSectionContribs();

View File

@ -62,6 +62,7 @@
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h" #include "llvm/Support/Process.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Signals.h" #include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -173,6 +174,16 @@ cl::opt<bool> DumpPageStats(
"page-stats", "page-stats",
cl::desc("dump allocation stats of the pages in the MSF file"), cl::desc("dump allocation stats of the pages in the MSF file"),
cl::cat(MsfOptions), cl::sub(RawSubcommand)); cl::cat(MsfOptions), cl::sub(RawSubcommand));
cl::opt<std::string>
DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"),
cl::desc("Dump binary data from specified range."),
cl::cat(MsfOptions), cl::sub(RawSubcommand));
llvm::Optional<BlockRange> DumpBlockRange;
cl::list<uint32_t>
DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
cl::desc("Dump binary data from specified streams."),
cl::cat(MsfOptions), cl::sub(RawSubcommand));
// TYPE OPTIONS // TYPE OPTIONS
cl::opt<bool> cl::opt<bool>
@ -225,14 +236,6 @@ cl::opt<bool> DumpSectionHeaders("section-headers",
cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions), cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
cl::sub(RawSubcommand)); cl::sub(RawSubcommand));
cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
cl::cat(MiscOptions),
cl::sub(RawSubcommand));
cl::opt<std::string> DumpStreamDataName("stream-name",
cl::desc("dump stream data"),
cl::cat(MiscOptions),
cl::sub(RawSubcommand));
cl::opt<bool> RawAll("all", cl::desc("Implies most other options."), cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
cl::cat(MiscOptions), cl::sub(RawSubcommand)); cl::cat(MiscOptions), cl::sub(RawSubcommand));
@ -549,6 +552,22 @@ int main(int argc_, const char *argv_[]) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
if (!opts::raw::DumpBlockRangeOpt.empty()) {
llvm::Regex R("^([0-9]+)(-([0-9]+))?$");
llvm::SmallVector<llvm::StringRef, 2> Matches;
if (!R.match(opts::raw::DumpBlockRangeOpt, &Matches)) {
errs() << "Argument '" << opts::raw::DumpBlockRangeOpt
<< "' invalid format.\n";
errs().flush();
exit(1);
}
opts::raw::DumpBlockRange.emplace();
Matches[1].getAsInteger(10, opts::raw::DumpBlockRange->Min);
if (!Matches[3].empty()) {
opts::raw::DumpBlockRange->Max.emplace();
Matches[3].getAsInteger(10, *opts::raw::DumpBlockRange->Max);
}
}
if (opts::RawSubcommand && opts::raw::RawAll) { if (opts::RawSubcommand && opts::raw::RawAll) {
opts::raw::DumpHeaders = true; opts::raw::DumpHeaders = true;
@ -589,12 +608,10 @@ int main(int argc_, const char *argv_[]) {
} }
// When adding filters for excluded compilands and types, we need to // When adding filters for excluded compilands and types, we need to
// remember // remember that these are regexes. So special characters such as * and \
// that these are regexes. So special characters such as * and \ need to be // need to be escaped in the regex. In the case of a literal \, this means
// escaped in the regex. In the case of a literal \, this means it needs to // it needs to be escaped again in the C++. So matching a single \ in the
// be escaped again in the C++. So matching a single \ in the input // input requires 4 \es in the C++.
// requires
// 4 \es in the C++.
if (opts::pretty::ExcludeCompilerGenerated) { if (opts::pretty::ExcludeCompilerGenerated) {
opts::pretty::ExcludeTypes.push_back("__vc_attributes"); opts::pretty::ExcludeTypes.push_back("__vc_attributes");
opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*"); opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");

View File

@ -10,6 +10,7 @@
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H #ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H #define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
#include "llvm/ADT/Optional.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -34,6 +35,14 @@ extern llvm::cl::list<std::string> IncludeCompilands;
} }
namespace raw { namespace raw {
struct BlockRange {
uint32_t Min;
llvm::Optional<uint32_t> Max;
};
extern llvm::Optional<BlockRange> DumpBlockRange;
extern llvm::cl::list<uint32_t> DumpStreamData;
extern llvm::cl::opt<bool> DumpHeaders; extern llvm::cl::opt<bool> DumpHeaders;
extern llvm::cl::opt<bool> DumpStreamBlocks; extern llvm::cl::opt<bool> DumpStreamBlocks;
extern llvm::cl::opt<bool> DumpStreamSummary; extern llvm::cl::opt<bool> DumpStreamSummary;
@ -43,8 +52,6 @@ extern llvm::cl::opt<bool> DumpTpiRecordBytes;
extern llvm::cl::opt<bool> DumpTpiRecords; extern llvm::cl::opt<bool> DumpTpiRecords;
extern llvm::cl::opt<bool> DumpIpiRecords; extern llvm::cl::opt<bool> DumpIpiRecords;
extern llvm::cl::opt<bool> DumpIpiRecordBytes; extern llvm::cl::opt<bool> DumpIpiRecordBytes;
extern llvm::cl::opt<std::string> DumpStreamDataIdx;
extern llvm::cl::opt<std::string> DumpStreamDataName;
extern llvm::cl::opt<bool> DumpModules; extern llvm::cl::opt<bool> DumpModules;
extern llvm::cl::opt<bool> DumpModuleFiles; extern llvm::cl::opt<bool> DumpModuleFiles;
extern llvm::cl::opt<bool> DumpModuleSyms; extern llvm::cl::opt<bool> DumpModuleSyms;