diff options
| -rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-headers.test | 6 | ||||
| -rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-raw-blocks.test | 17 | ||||
| -rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test | 6 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp | 167 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/BytesOutputStyle.h | 41 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp | 109 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/LinePrinter.cpp | 14 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/LinePrinter.h | 2 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp | 87 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbutil/llvm-pdbutil.h | 9 |
11 files changed, 307 insertions, 152 deletions
diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index afedbb5c257..e6ee12b6d10 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -1,7 +1,7 @@ -; RUN: llvm-pdbutil raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s -; RUN: llvm-pdbutil raw -summary -modules -files \ +; RUN: llvm-pdbutil dump -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s +; RUN: llvm-pdbutil dump -summary -modules -files \ ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s -; RUN: not llvm-pdbutil raw -summary %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s +; RUN: not llvm-pdbutil dump -summary %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s ALL: Summary ALL-NEXT: ============================================================ diff --git a/llvm/test/DebugInfo/PDB/pdbdump-raw-blocks.test b/llvm/test/DebugInfo/PDB/pdbdump-raw-blocks.test index e333a05fce3..16cd8e7a469 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-raw-blocks.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-raw-blocks.test @@ -1,8 +1,9 @@ -; RUN: llvm-pdbutil dump -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s -; RUN: llvm-pdbutil dump -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s -; RUN: not llvm-pdbutil dump -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s -; RUN: not llvm-pdbutil dump -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s -; RUN: not llvm-pdbutil dump -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s +; RUN: llvm-pdbutil bytes -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s +; RUN: llvm-pdbutil bytes -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s +; RUN: llvm-pdbutil bytes -block-data=0-0x1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s +; RUN: not llvm-pdbutil bytes -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s +; RUN: not llvm-pdbutil bytes -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s +; RUN: not llvm-pdbutil bytes -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s BLOCK0: MSF Blocks BLOCK0-NEXT: ============================================================ @@ -21,9 +22,9 @@ BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 00000000 18000000 00 BLOCK01-NEXT: 0040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| BLOCK01-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| BLOCK01: Block 1 ( -BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| -BLOCK01-NEXT: 0020: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| -BLOCK01-NEXT: 0040: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NEXT: 1000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NEXT: 1020: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NEXT: 1040: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| BLOCK01-NOT: Block 2 ( BADSYNTAX: Argument '{{.*}}' invalid format. diff --git a/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test b/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test index 4022975e108..d8510a1af73 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test @@ -1,6 +1,6 @@ -; RUN: llvm-pdbutil dump -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM %s -; RUN: llvm-pdbutil dump -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s -; RUN: llvm-pdbutil dump -stream-data=1,100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BOTH %s +; RUN: llvm-pdbutil bytes -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM %s +; RUN: llvm-pdbutil bytes -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s +; RUN: llvm-pdbutil bytes -stream-data=1,100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BOTH %s STREAM: Stream Data STREAM-NEXT: ============================================================ diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp new file mode 100644 index 00000000000..af56092ce63 --- /dev/null +++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp @@ -0,0 +1,167 @@ +//===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "BytesOutputStyle.h" + +#include "StreamUtil.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace { +struct StreamSpec { + uint32_t SI = 0; + uint32_t Begin = 0; + uint32_t Size = 0; +}; +} // namespace + +static Expected<StreamSpec> parseStreamSpec(StringRef Str) { + StreamSpec Result; + if (Str.consumeInteger(0, Result.SI)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + if (Str.consume_front(":")) { + if (Str.consumeInteger(0, Result.Begin)) + return make_error<RawError>(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (Str.consume_front("@")) { + if (Str.consumeInteger(0, Result.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 Result; +} + +static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) { + SmallVector<StreamSpec, 2> Result; + + for (auto &Str : opts::bytes::DumpStreamData) { + auto ESS = parseStreamSpec(Str); + if (!ESS) { + P.formatLine("Error parsing stream spec {0}: {1}", Str, + toString(ESS.takeError())); + continue; + } + Result.push_back(*ESS); + } + return Result; +} + +static void printHeader(LinePrinter &P, const Twine &S) { + P.NewLine(); + P.formatLine("{0,=60}", S); + P.formatLine("{0}", fmt_repeat('=', 60)); +} + +BytesOutputStyle::BytesOutputStyle(PDBFile &File) + : File(File), P(2, false, outs()) {} + +Error BytesOutputStyle::dump() { + + if (opts::bytes::DumpBlockRange.hasValue()) { + auto &R = *opts::bytes::DumpBlockRange; + uint32_t Max = R.Max.getValueOr(R.Min); + + if (Max < R.Min) + return make_error<StringError>( + "Invalid block range specified. Max < Min", + inconvertibleErrorCode()); + if (Max >= File.getBlockCount()) + return make_error<StringError>( + "Invalid block range specified. Requested block out of bounds", + inconvertibleErrorCode()); + + dumpBlockRanges(R.Min, Max); + P.NewLine(); + } + + if (!opts::bytes::DumpStreamData.empty()) { + dumpStreamBytes(); + P.NewLine(); + } + return Error::success(); +} + +void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) { + printHeader(P, "MSF Blocks"); + + AutoIndent Indent(P); + for (uint32_t I = Min; I <= Max; ++I) { + uint64_t Base = I; + Base *= File.getBlockSize(); + + auto ExpectedData = File.getBlockData(I, File.getBlockSize()); + if (!ExpectedData) { + P.formatLine("Could not get block {0}. Reason = {1}", I, + toString(ExpectedData.takeError())); + continue; + } + std::string Label = formatv("Block {0}", I).str(); + P.formatBinary(Label, *ExpectedData, Base, 0); + } +} + +void BytesOutputStyle::dumpStreamBytes() { + if (StreamPurposes.empty()) + discoverStreamPurposes(File, StreamPurposes); + + printHeader(P, "Stream Data"); + ExitOnError Err("Unexpected error reading stream data"); + + auto Specs = parseStreamSpecs(P); + + for (const auto &Spec : Specs) { + uint32_t End = 0; + + AutoIndent Indent(P); + if (Spec.SI >= File.getNumStreams()) { + P.formatLine("Stream {0}: Not present", Spec.SI); + continue; + } + + auto S = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), Spec.SI, File.getAllocator()); + if (!S) { + P.NewLine(); + P.formatLine("Stream {0}: Not present", Spec.SI); + continue; + } + + if (Spec.Size == 0) + End = S->getLength(); + else + End = std::min(Spec.Begin + Spec.Size, S->getLength()); + uint32_t Size = End - Spec.Begin; + + P.formatLine("Stream {0} ({1:N} bytes): {2}", Spec.SI, S->getLength(), + StreamPurposes[Spec.SI]); + AutoIndent Indent2(P); + + BinaryStreamReader R(*S); + ArrayRef<uint8_t> StreamData; + Err(R.readBytes(StreamData, S->getLength())); + StreamData = StreamData.slice(Spec.Begin, Size); + P.formatBinary("Data", StreamData, Spec.Begin); + } +} diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.h b/llvm/tools/llvm-pdbutil/BytesOutputStyle.h new file mode 100644 index 00000000000..7fd35e7860b --- /dev/null +++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.h @@ -0,0 +1,41 @@ +//===- BytesOutputStyle.h ------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_BYTESOUTPUTSTYLE_H +#define LLVM_TOOLS_LLVMPDBDUMP_BYTESOUTPUTSTYLE_H + +#include "LinePrinter.h" +#include "OutputStyle.h" + +#include "llvm/Support/Error.h" + +namespace llvm { + +namespace pdb { + +class PDBFile; + +class BytesOutputStyle : public OutputStyle { +public: + BytesOutputStyle(PDBFile &File); + + Error dump() override; + +private: + void dumpBlockRanges(uint32_t Min, uint32_t Max); + void dumpStreamBytes(); + + PDBFile &File; + LinePrinter P; + SmallVector<std::string, 8> StreamPurposes; +}; +} // namespace pdb +} // namespace llvm + +#endif diff --git a/llvm/tools/llvm-pdbutil/CMakeLists.txt b/llvm/tools/llvm-pdbutil/CMakeLists.txt index 8ebe0133f5e..7a3245424ef 100644 --- a/llvm/tools/llvm-pdbutil/CMakeLists.txt +++ b/llvm/tools/llvm-pdbutil/CMakeLists.txt @@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-pdbutil Analyze.cpp + BytesOutputStyle.cpp Diff.cpp DumpOutputStyle.cpp llvm-pdbutil.cpp diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index ea7d9f1f708..a05e5cf03e9 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -80,18 +80,6 @@ Error DumpOutputStyle::dump() { P.NewLine(); } - if (opts::dump::DumpBlockRange.hasValue()) { - if (auto EC = dumpBlockRanges()) - return EC; - P.NewLine(); - } - - if (!opts::dump::DumpStreamData.empty()) { - if (auto EC = dumpStreamBytes()) - return EC; - P.NewLine(); - } - if (opts::dump::DumpStringTable) { if (auto EC = dumpStringTable()) return EC; @@ -216,103 +204,6 @@ Error DumpOutputStyle::dumpStreamSummary() { return Error::success(); } -Error DumpOutputStyle::dumpBlockRanges() { - printHeader(P, "MSF Blocks"); - - auto &R = *opts::dump::DumpBlockRange; - uint32_t Max = R.Max.getValueOr(R.Min); - - AutoIndent Indent(P); - 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)); - - for (uint32_t I = R.Min; I <= Max; ++I) { - auto ExpectedData = File.getBlockData(I, File.getBlockSize()); - if (!ExpectedData) - return ExpectedData.takeError(); - std::string Label = formatv("Block {0}", I).str(); - P.formatBinary(Label, *ExpectedData, 0); - } - - 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 DumpOutputStyle::dumpStreamBytes() { - if (StreamPurposes.empty()) - discoverStreamPurposes(File, StreamPurposes); - - printHeader(P, "Stream Data"); - ExitOnError Err("Unexpected error reading stream data"); - - for (auto &Str : opts::dump::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; - - AutoIndent Indent(P); - if (SI >= File.getNumStreams()) { - P.formatLine("Stream {0}: Not present", SI); - continue; - } - - auto S = MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator()); - if (!S) { - P.NewLine(); - P.formatLine("Stream {0}: Not present", SI); - continue; - } - - if (Size == 0) - End = S->getLength(); - else - End = std::min(Begin + Size, S->getLength()); - - P.formatLine("Stream {0} ({1:N} bytes): {2}", SI, S->getLength(), - StreamPurposes[SI]); - AutoIndent Indent2(P); - - BinaryStreamReader R(*S); - ArrayRef<uint8_t> StreamData; - Err(R.readBytes(StreamData, S->getLength())); - Size = End - Begin; - StreamData = StreamData.slice(Begin, Size); - P.formatBinary("Data", StreamData, Begin); - } - return Error::success(); -} - static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File, uint32_t Index) { ExitOnError Err("Unexpected error"); diff --git a/llvm/tools/llvm-pdbutil/LinePrinter.cpp b/llvm/tools/llvm-pdbutil/LinePrinter.cpp index 718d3394e21..3e736d90426 100644 --- a/llvm/tools/llvm-pdbutil/LinePrinter.cpp +++ b/llvm/tools/llvm-pdbutil/LinePrinter.cpp @@ -106,6 +106,20 @@ void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, OS << ")"; } +void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, + uint64_t Base, uint32_t StartOffset) { + NewLine(); + OS << Label << " ("; + if (!Data.empty()) { + OS << "\n"; + Base += StartOffset; + OS << format_bytes_with_ascii(Data, Base, 32, 4, + CurrentIndent + IndentSpaces, true); + NewLine(); + } + OS << ")"; +} + bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) { if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters)) return true; diff --git a/llvm/tools/llvm-pdbutil/LinePrinter.h b/llvm/tools/llvm-pdbutil/LinePrinter.h index f4fd22bcb6f..9293c49132d 100644 --- a/llvm/tools/llvm-pdbutil/LinePrinter.h +++ b/llvm/tools/llvm-pdbutil/LinePrinter.h @@ -45,6 +45,8 @@ public: void formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint32_t StartOffset); + void formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint64_t BaseAddr, + uint32_t StartOffset); bool hasColor() const { return UseColor; } raw_ostream &getStream() { return OS; } diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index 658833de625..a86dccba50b 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -14,6 +14,7 @@ #include "llvm-pdbutil.h" #include "Analyze.h" +#include "BytesOutputStyle.h" #include "Diff.h" #include "DumpOutputStyle.h" #include "LinePrinter.h" @@ -87,6 +88,8 @@ using namespace llvm::pdb; namespace opts { cl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info"); +cl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file"); + cl::SubCommand PrettySubcommand("pretty", "Dump semantic information about types and symbols"); @@ -263,6 +266,26 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::OptionCategory FileOptions("Module & File Options"); +namespace bytes { +llvm::Optional<BlockRange> DumpBlockRange; + +cl::opt<std::string> + DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"), + cl::desc("Dump binary data from specified range."), + cl::sub(BytesSubcommand)); + +cl::list<std::string> + DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), + cl::sub(BytesSubcommand)); + +cl::list<std::string> InputFilenames(cl::Positional, + cl::desc("<input PDB files>"), + cl::OneOrMore, cl::sub(BytesSubcommand)); + +} // namespace bytes + namespace dump { cl::OptionCategory MsfOptions("MSF Container Options"); @@ -276,17 +299,6 @@ cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"), cl::opt<bool> DumpStreams("streams", cl::desc("dump summary of the PDB streams"), cl::cat(MsfOptions), cl::sub(DumpSubcommand)); -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(DumpSubcommand)); -llvm::Optional<BlockRange> DumpBlockRange; - -cl::list<std::string> - DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams. Format " - "is SN[:Start][@Size]"), - cl::cat(MsfOptions), cl::sub(DumpSubcommand)); // TYPE OPTIONS cl::opt<bool> DumpTypes("types", @@ -626,6 +638,15 @@ static void dumpRaw(StringRef Path) { ExitOnErr(O->dump()); } +static void dumpBytes(StringRef Path) { + std::unique_ptr<IPDBSession> Session; + auto &File = loadPDB(Path, Session); + + auto O = llvm::make_unique<BytesOutputStyle>(File); + + ExitOnErr(O->dump()); +} + static void dumpAnalysis(StringRef Path) { std::unique_ptr<IPDBSession> Session; auto &File = loadPDB(Path, Session); @@ -882,6 +903,27 @@ static void mergePdbs() { ExitOnErr(Builder.commit(OutFile)); } +static bool validateBlockRangeArgument() { + if (opts::bytes::DumpBlockRangeOpt.empty()) + return true; + + llvm::Regex R("^([^-]+)(-([^-]+))?$"); + llvm::SmallVector<llvm::StringRef, 2> Matches; + if (!R.match(opts::bytes::DumpBlockRangeOpt, &Matches)) + return false; + + opts::bytes::DumpBlockRange.emplace(); + if (!to_integer(Matches[1], opts::bytes::DumpBlockRange->Min)) + return false; + + if (!Matches[3].empty()) { + opts::bytes::DumpBlockRange->Max.emplace(); + if (!to_integer(Matches[3], *opts::bytes::DumpBlockRange->Max)) + return false; + } + return true; +} + int main(int argc_, const char *argv_[]) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv_[0]); @@ -897,21 +939,11 @@ int main(int argc_, const char *argv_[]) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); - if (!opts::dump::DumpBlockRangeOpt.empty()) { - llvm::Regex R("^([0-9]+)(-([0-9]+))?$"); - llvm::SmallVector<llvm::StringRef, 2> Matches; - if (!R.match(opts::dump::DumpBlockRangeOpt, &Matches)) { - errs() << "Argument '" << opts::dump::DumpBlockRangeOpt - << "' invalid format.\n"; - errs().flush(); - exit(1); - } - opts::dump::DumpBlockRange.emplace(); - Matches[1].getAsInteger(10, opts::dump::DumpBlockRange->Min); - if (!Matches[3].empty()) { - opts::dump::DumpBlockRange->Max.emplace(); - Matches[3].getAsInteger(10, *opts::dump::DumpBlockRange->Max); - } + if (!validateBlockRangeArgument()) { + errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt + << "' invalid format.\n"; + errs().flush(); + exit(1); } if (opts::DumpSubcommand) { @@ -1018,6 +1050,9 @@ int main(int argc_, const char *argv_[]) { } else if (opts::DumpSubcommand) { std::for_each(opts::dump::InputFilenames.begin(), opts::dump::InputFilenames.end(), dumpRaw); + } else if (opts::BytesSubcommand) { + std::for_each(opts::bytes::InputFilenames.begin(), + opts::bytes::InputFilenames.end(), dumpBytes); } else if (opts::DiffSubcommand) { if (opts::diff::InputFilenames.size() != 2) { errs() << "diff subcommand expects exactly 2 arguments.\n"; diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h index c18d1b79549..811037ad622 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h @@ -92,16 +92,19 @@ extern llvm::cl::opt<ClassDefinitionFormat> ClassFormat; extern llvm::cl::opt<uint32_t> ClassRecursionDepth; } -namespace dump { +namespace bytes { struct BlockRange { uint32_t Min; llvm::Optional<uint32_t> Max; }; +extern llvm::Optional<BlockRange> DumpBlockRange; +extern llvm::cl::list<std::string> DumpStreamData; +} // namespace bytes + +namespace dump { extern llvm::cl::opt<bool> DumpSummary; extern llvm::cl::opt<bool> DumpStreams; -extern llvm::Optional<BlockRange> DumpBlockRange; -extern llvm::cl::list<std::string> DumpStreamData; extern llvm::cl::opt<bool> DumpLines; extern llvm::cl::opt<bool> DumpInlineeLines; |

