diff options
-rw-r--r-- | llvm/include/llvm/Support/ScopedPrinter.h | 7 | ||||
-rw-r--r-- | llvm/lib/Support/ScopedPrinter.cpp | 6 | ||||
-rw-r--r-- | llvm/test/tools/llvm-pdbdump/raw-stream-data.test | 47 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp | 43 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 5 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.h | 2 |
6 files changed, 102 insertions, 8 deletions
diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h index a2f2e098543..1b665193221 100644 --- a/llvm/include/llvm/Support/ScopedPrinter.h +++ b/llvm/include/llvm/Support/ScopedPrinter.h @@ -295,6 +295,11 @@ public: printBinaryImpl(Label, StringRef(), V, false); } + void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value, + uint32_t StartOffset) { + printBinaryImpl(Label, StringRef(), Value, true, StartOffset); + } + void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) { printBinaryImpl(Label, StringRef(), Value, true); } @@ -333,7 +338,7 @@ private: } void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, - bool Block); + bool Block, uint32_t StartOffset = 0); raw_ostream &OS; int IndentLevel; diff --git a/llvm/lib/Support/ScopedPrinter.cpp b/llvm/lib/Support/ScopedPrinter.cpp index d8ee1efd8f3..537ff62c7b0 100644 --- a/llvm/lib/Support/ScopedPrinter.cpp +++ b/llvm/lib/Support/ScopedPrinter.cpp @@ -21,7 +21,8 @@ const std::string to_hexString(uint64_t Value, bool UpperCase) { } void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str, - ArrayRef<uint8_t> Data, bool Block) { + ArrayRef<uint8_t> Data, bool Block, + uint32_t StartOffset) { if (Data.size() > 16) Block = true; @@ -31,7 +32,8 @@ void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str, OS << ": " << Str; OS << " (\n"; if (!Data.empty()) - OS << format_bytes_with_ascii(Data, 0, 16, 4, (IndentLevel + 1) * 2, true) + OS << format_bytes_with_ascii(Data, StartOffset, 16, 4, + (IndentLevel + 1) * 2, true) << "\n"; startLine() << ")\n"; } else { diff --git a/llvm/test/tools/llvm-pdbdump/raw-stream-data.test b/llvm/test/tools/llvm-pdbdump/raw-stream-data.test new file mode 100644 index 00000000000..d55980632d4 --- /dev/null +++ b/llvm/test/tools/llvm-pdbdump/raw-stream-data.test @@ -0,0 +1,47 @@ +; RUN: llvm-pdbdump raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
+; RUN: | FileCheck %s -check-prefix=FULL_STREAM
+; RUN: llvm-pdbdump raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
+; RUN: | FileCheck %s -check-prefix=OFFSET_STREAM
+; RUN: llvm-pdbdump raw -stream-data=8:4@24 %p/Inputs/LoadAddressTest.pdb \
+; RUN: | FileCheck %s -check-prefix=OFFSET_AND_LENGTH
+
+FULL_STREAM: Stream Data {
+FULL_STREAM-NEXT: Stream {
+FULL_STREAM-NEXT: Index: 8
+FULL_STREAM-NEXT: Type: Public Symbol Records
+FULL_STREAM-NEXT: Size: 40
+FULL_STREAM-NEXT: Blocks:
+FULL_STREAM-NEXT: Data (
+FULL_STREAM-NEXT: 0000: 12000E11 02000000 10000000 01005F6D |.............._m|
+FULL_STREAM-NEXT: 0010: 61696E00 12002511 00000000 88000000 |ain...%.........|
+FULL_STREAM-NEXT: 0020: 01006D61 696E0000 |..main..|
+FULL_STREAM-NEXT: )
+FULL_STREAM-NEXT: }
+FULL_STREAM-NEXT: }
+
+OFFSET_STREAM: Stream Data {
+OFFSET_STREAM-NEXT: Stream {
+OFFSET_STREAM-NEXT: Index: 8
+OFFSET_STREAM-NEXT: Type: Public Symbol Records
+OFFSET_STREAM-NEXT: Size: 40
+OFFSET_STREAM-NEXT: Blocks:
+OFFSET_STREAM-NEXT: Data (
+OFFSET_STREAM-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|
+OFFSET_STREAM-NEXT: 0014: 12002511 00000000 88000000 01006D61 |..%...........ma|
+OFFSET_STREAM-NEXT: 0024: 696E0000 |in..|
+OFFSET_STREAM-NEXT: )
+OFFSET_STREAM-NEXT: }
+OFFSET_STREAM-NEXT:}
+
+OFFSET_AND_LENGTH: Stream Data {
+OFFSET_AND_LENGTH-NEXT: Stream {
+OFFSET_AND_LENGTH-NEXT: Index: 8
+OFFSET_AND_LENGTH-NEXT: Type: Public Symbol Records
+OFFSET_AND_LENGTH-NEXT: Size: 40
+OFFSET_AND_LENGTH-NEXT: Blocks:
+OFFSET_AND_LENGTH-NEXT: Data (
+OFFSET_AND_LENGTH-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|
+OFFSET_AND_LENGTH-NEXT: 0014: 12002511 00000000 |..%.....|
+OFFSET_AND_LENGTH-NEXT: )
+OFFSET_AND_LENGTH-NEXT: }
+OFFSET_AND_LENGTH-NEXT:}
\ No newline at end of file diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 20223ac60f4..705728e27d0 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -319,6 +319,27 @@ Error LLVMOutputStyle::dumpBlockRanges() { return Error::success(); } +static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset, + uint32_t &Size) { + if (Str.consumeInteger(0, SI)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + if (Str.consume_front(":")) { + if (Str.consumeInteger(0, Offset)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (Str.consume_front("@")) { + if (Str.consumeInteger(0, Size)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (!Str.empty()) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + return Error::success(); +} + Error LLVMOutputStyle::dumpStreamBytes() { if (opts::raw::DumpStreamData.empty()) return Error::success(); @@ -327,7 +348,15 @@ Error LLVMOutputStyle::dumpStreamBytes() { discoverStreamPurposes(File, StreamPurposes); DictScope D(P, "Stream Data"); - for (uint32_t SI : opts::raw::DumpStreamData) { + for (auto &Str : opts::raw::DumpStreamData) { + uint32_t SI = 0; + uint32_t Begin = 0; + uint32_t Size = 0; + uint32_t End = 0; + + if (auto EC = parseStreamSpec(Str, SI, Begin, Size)) + return EC; + if (SI >= File.getNumStreams()) return make_error<RawError>(raw_error_code::no_stream); @@ -336,6 +365,14 @@ Error LLVMOutputStyle::dumpStreamBytes() { if (!S) continue; DictScope DD(P, "Stream"); + if (Size == 0) + End = S->getLength(); + else { + End = Begin + Size; + if (End >= S->getLength()) + return make_error<RawError>(raw_error_code::index_out_of_bounds, + "Stream is not long enough!"); + } P.printNumber("Index", SI); P.printString("Type", StreamPurposes[SI]); @@ -347,7 +384,9 @@ Error LLVMOutputStyle::dumpStreamBytes() { ArrayRef<uint8_t> StreamData; if (auto EC = R.readBytes(StreamData, S->getLength())) return EC; - P.printBinaryBlock("Data", StreamData); + Size = End - Begin; + StreamData = StreamData.slice(Begin, Size); + P.printBinaryBlock("Data", StreamData, Begin); } return Error::success(); } diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 3d7dbffb0d5..e6d363e1626 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -261,9 +261,10 @@ cl::opt<std::string> cl::cat(MsfOptions), cl::sub(RawSubcommand)); llvm::Optional<BlockRange> DumpBlockRange; -cl::list<uint32_t> +cl::list<std::string> DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams."), + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), cl::cat(MsfOptions), cl::sub(RawSubcommand)); // TYPE OPTIONS diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h index f080d6d5525..8b1dde9399b 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h @@ -60,7 +60,7 @@ struct BlockRange { }; extern llvm::Optional<BlockRange> DumpBlockRange; -extern llvm::cl::list<uint32_t> DumpStreamData; +extern llvm::cl::list<std::string> DumpStreamData; extern llvm::cl::opt<bool> CompactRecords; extern llvm::cl::opt<bool> DumpGlobals; |