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);
}
}
void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
- bool Block);
+ bool Block, uint32_t StartOffset = 0);
raw_ostream &OS;
int IndentLevel;
}
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;
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 {
--- /dev/null
+; RUN: llvm-pdbdump raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \\r
+; RUN: | FileCheck %s -check-prefix=FULL_STREAM\r
+; RUN: llvm-pdbdump raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \\r
+; RUN: | FileCheck %s -check-prefix=OFFSET_STREAM\r
+; RUN: llvm-pdbdump raw -stream-data=8:4@24 %p/Inputs/LoadAddressTest.pdb \\r
+; RUN: | FileCheck %s -check-prefix=OFFSET_AND_LENGTH\r
+\r
+FULL_STREAM: Stream Data {\r
+FULL_STREAM-NEXT: Stream {\r
+FULL_STREAM-NEXT: Index: 8\r
+FULL_STREAM-NEXT: Type: Public Symbol Records\r
+FULL_STREAM-NEXT: Size: 40\r
+FULL_STREAM-NEXT: Blocks:\r
+FULL_STREAM-NEXT: Data (\r
+FULL_STREAM-NEXT: 0000: 12000E11 02000000 10000000 01005F6D |.............._m|\r
+FULL_STREAM-NEXT: 0010: 61696E00 12002511 00000000 88000000 |ain...%.........|\r
+FULL_STREAM-NEXT: 0020: 01006D61 696E0000 |..main..|\r
+FULL_STREAM-NEXT: )\r
+FULL_STREAM-NEXT: }\r
+FULL_STREAM-NEXT: }\r
+\r
+OFFSET_STREAM: Stream Data {\r
+OFFSET_STREAM-NEXT: Stream {\r
+OFFSET_STREAM-NEXT: Index: 8\r
+OFFSET_STREAM-NEXT: Type: Public Symbol Records\r
+OFFSET_STREAM-NEXT: Size: 40\r
+OFFSET_STREAM-NEXT: Blocks: \r
+OFFSET_STREAM-NEXT: Data (\r
+OFFSET_STREAM-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|\r
+OFFSET_STREAM-NEXT: 0014: 12002511 00000000 88000000 01006D61 |..%...........ma|\r
+OFFSET_STREAM-NEXT: 0024: 696E0000 |in..|\r
+OFFSET_STREAM-NEXT: )\r
+OFFSET_STREAM-NEXT: }\r
+OFFSET_STREAM-NEXT:}\r
+\r
+OFFSET_AND_LENGTH: Stream Data {\r
+OFFSET_AND_LENGTH-NEXT: Stream {\r
+OFFSET_AND_LENGTH-NEXT: Index: 8\r
+OFFSET_AND_LENGTH-NEXT: Type: Public Symbol Records\r
+OFFSET_AND_LENGTH-NEXT: Size: 40\r
+OFFSET_AND_LENGTH-NEXT: Blocks: \r
+OFFSET_AND_LENGTH-NEXT: Data (\r
+OFFSET_AND_LENGTH-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|\r
+OFFSET_AND_LENGTH-NEXT: 0014: 12002511 00000000 |..%.....|\r
+OFFSET_AND_LENGTH-NEXT: )\r
+OFFSET_AND_LENGTH-NEXT: }\r
+OFFSET_AND_LENGTH-NEXT:}
\ No newline at end of file
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();
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);
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]);
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();
}
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
};
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;