]> granicus.if.org Git - llvm/commitdiff
[llvm-pdbutil] Create a "bytes" subcommand.
authorZachary Turner <zturner@google.com>
Thu, 22 Jun 2017 20:58:11 +0000 (20:58 +0000)
committerZachary Turner <zturner@google.com>
Thu, 22 Jun 2017 20:58:11 +0000 (20:58 +0000)
This idea originally came about when I was doing some deep
investigation of why certain bytes in a PDB that we round-tripped
differed from their original bytes in the source PDB.  I found
myself having to hack up the code in many places to dump the
bytes of this substream, or that record.  It would be nice if
we could just do this for every possible stream, substream,
debug chunk type, etc.

It doesn't make sense to put this under dump because there's just
so many options that would detract from the more common use case
of just dumping deserialized records.  So making a new subcommand
seems like the most logical course of action.  In doing so, we
already have two command line options that are suitable for this
new subcommand, so start out by moving them there.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306056 91177308-0d34-0410-b5e6-96231b3b80d8

test/DebugInfo/PDB/pdbdump-headers.test
test/DebugInfo/PDB/pdbdump-raw-blocks.test
test/DebugInfo/PDB/pdbdump-raw-stream.test
tools/llvm-pdbutil/BytesOutputStyle.cpp [new file with mode: 0644]
tools/llvm-pdbutil/BytesOutputStyle.h [new file with mode: 0644]
tools/llvm-pdbutil/CMakeLists.txt
tools/llvm-pdbutil/DumpOutputStyle.cpp
tools/llvm-pdbutil/LinePrinter.cpp
tools/llvm-pdbutil/LinePrinter.h
tools/llvm-pdbutil/llvm-pdbutil.cpp
tools/llvm-pdbutil/llvm-pdbutil.h

index afedbb5c25768ecc5e1d6a777e1c58d2e314e047..e6ee12b6d10e081e59801f7b646e4b5cbff37293 100644 (file)
@@ -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: ============================================================
index e333a05fce33a04d47e64f81799506a10f34afcb..16cd8e7a469409e5dc0b153e044e55b5e2266d11 100644 (file)
@@ -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.
index 4022975e108c73a85c3ee80d9e178b36848a0d14..d8510a1af733a3c1c4df0e997acb495888f55b6c 100644 (file)
@@ -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/tools/llvm-pdbutil/BytesOutputStyle.cpp b/tools/llvm-pdbutil/BytesOutputStyle.cpp
new file mode 100644 (file)
index 0000000..af56092
--- /dev/null
@@ -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/tools/llvm-pdbutil/BytesOutputStyle.h b/tools/llvm-pdbutil/BytesOutputStyle.h
new file mode 100644 (file)
index 0000000..7fd35e7
--- /dev/null
@@ -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
index 8ebe0133f5e349f36d099c85cfe8bd312128c665..7a3245424efc6da891816375acfefd8a8e324f6d 100644 (file)
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_tool(llvm-pdbutil
   Analyze.cpp
+  BytesOutputStyle.cpp
   Diff.cpp
   DumpOutputStyle.cpp
   llvm-pdbutil.cpp
index ea7d9f1f70897c2d0a977f7b5495ca704a852aa8..a05e5cf03e99b0b1737ec0f36fd7ef93a92d68a4 100644 (file)
@@ -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");
index 718d3394e211d19df3451b3ec4d557e06e68d7e4..3e736d904267a9a35819d38bb8dc82b2ac46d88c 100644 (file)
@@ -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;
index f4fd22bcb6f450523b69da8bf1db8625f285dd31..9293c49132d58dc6df746cd160d5b0506fb84640 100644 (file)
@@ -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; }
index 658833de625c5eb2c686114c9d9fbcd03cb921f7..a86dccba50bcac0b202757e453c541b129b492ac 100644 (file)
@@ -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";
index c18d1b79549bfac27b1e7801d6187bc278933a5d..811037ad62203f0988b1be0de64d3152e6614126 100644 (file)
@@ -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;