[llvm] r329207 - [llvm-pdbutil] Add the ability to explain binary files.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 4 10:29:10 PDT 2018


Author: zturner
Date: Wed Apr  4 10:29:09 2018
New Revision: 329207

URL: http://llvm.org/viewvc/llvm-project?rev=329207&view=rev
Log:
[llvm-pdbutil] Add the ability to explain binary files.

Using this, you can use llvm-pdbutil to export the contents of a
stream to a binary file, then run explain on the binary file so
that it treats the offset as an offset into the stream instead
of an offset into a file.  This makes it easy to compare the
contents of the same stream from two different files.

Modified:
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
    llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp
    llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.h
    llvm/trunk/tools/llvm-pdbutil/InputFile.cpp
    llvm/trunk/tools/llvm-pdbutil/InputFile.h
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h Wed Apr  4 10:29:09 2018
@@ -38,9 +38,9 @@ class DbiStream {
   friend class DbiStreamBuilder;
 
 public:
-  DbiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+  explicit DbiStream(std::unique_ptr<BinaryStream> Stream);
   ~DbiStream();
-  Error reload();
+  Error reload(PDBFile *Pdb);
 
   PdbRaw_DbiVer getDbiVersion() const;
   uint32_t getAge() const;
@@ -89,12 +89,11 @@ public:
 
 private:
   Error initializeSectionContributionData();
-  Error initializeSectionHeadersData();
+  Error initializeSectionHeadersData(PDBFile *Pdb);
   Error initializeSectionMapData();
-  Error initializeFpoRecords();
+  Error initializeFpoRecords(PDBFile *Pdb);
 
-  PDBFile &Pdb;
-  std::unique_ptr<msf::MappedBlockStream> Stream;
+  std::unique_ptr<BinaryStream> Stream;
 
   PDBStringTable ECNames;
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h Wed Apr  4 10:29:09 2018
@@ -30,7 +30,7 @@ class InfoStream {
   friend class InfoStreamBuilder;
 
 public:
-  InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream);
+  InfoStream(std::unique_ptr<BinaryStream> Stream);
 
   Error reload();
 
@@ -56,7 +56,7 @@ public:
   StringMap<uint32_t> named_streams() const;
 
 private:
-  std::unique_ptr<msf::MappedBlockStream> Stream;
+  std::unique_ptr<BinaryStream> Stream;
 
   const InfoStreamHeader *Header;
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h Wed Apr  4 10:29:09 2018
@@ -112,6 +112,8 @@ struct DbiBuildNo {
 
   static const uint16_t BuildMajorMask = 0x7F00;
   static const uint16_t BuildMajorShift = 8;
+
+  static const uint16_t NewVersionFormatMask = 0x8000;
 };
 
 /// The fixed size header that appears at the beginning of the DBI Stream.

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp Wed Apr  4 10:29:09 2018
@@ -45,12 +45,12 @@ static Error loadSectionContribs(FixedSt
   return Error::success();
 }
 
-DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
-    : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
+DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
+    : Stream(std::move(Stream)), Header(nullptr) {}
 
 DbiStream::~DbiStream() = default;
 
-Error DbiStream::reload() {
+Error DbiStream::reload(PDBFile *Pdb) {
   BinaryStreamReader Reader(*Stream);
 
   if (Stream->getLength() < sizeof(DbiStreamHeader))
@@ -123,11 +123,11 @@ Error DbiStream::reload() {
 
   if (auto EC = initializeSectionContributionData())
     return EC;
-  if (auto EC = initializeSectionHeadersData())
+  if (auto EC = initializeSectionHeadersData(Pdb))
     return EC;
   if (auto EC = initializeSectionMapData())
     return EC;
-  if (auto EC = initializeFpoRecords())
+  if (auto EC = initializeFpoRecords(Pdb))
     return EC;
 
   if (Reader.bytesRemaining() > 0)
@@ -246,7 +246,10 @@ Error DbiStream::initializeSectionContri
 }
 
 // Initializes this->SectionHeaders.
-Error DbiStream::initializeSectionHeadersData() {
+Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
+  if (!Pdb)
+    return Error::success();
+
   if (DbgStreams.size() == 0)
     return Error::success();
 
@@ -254,11 +257,11 @@ Error DbiStream::initializeSectionHeader
   if (StreamNum == kInvalidStreamIndex)
     return Error::success();
 
-  if (StreamNum >= Pdb.getNumStreams())
+  if (StreamNum >= Pdb->getNumStreams())
     return make_error<RawError>(raw_error_code::no_stream);
 
   auto SHS = MappedBlockStream::createIndexedStream(
-      Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
+      Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
 
   size_t StreamLen = SHS->getLength();
   if (StreamLen % sizeof(object::coff_section))
@@ -276,7 +279,10 @@ Error DbiStream::initializeSectionHeader
 }
 
 // Initializes this->Fpos.
-Error DbiStream::initializeFpoRecords() {
+Error DbiStream::initializeFpoRecords(PDBFile *Pdb) {
+  if (!Pdb)
+    return Error::success();
+
   if (DbgStreams.size() == 0)
     return Error::success();
 
@@ -286,11 +292,11 @@ Error DbiStream::initializeFpoRecords()
   if (StreamNum == kInvalidStreamIndex)
     return Error::success();
 
-  if (StreamNum >= Pdb.getNumStreams())
+  if (StreamNum >= Pdb->getNumStreams())
     return make_error<RawError>(raw_error_code::no_stream);
 
   auto FS = MappedBlockStream::createIndexedStream(
-      Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
+      Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
 
   size_t StreamLen = FS->getLength();
   if (StreamLen % sizeof(object::FpoData))

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp Wed Apr  4 10:29:09 2018
@@ -20,7 +20,7 @@ using namespace llvm::codeview;
 using namespace llvm::msf;
 using namespace llvm::pdb;
 
-InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
+InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
     : Stream(std::move(Stream)), Header(nullptr) {}
 
 Error InfoStream::reload() {

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp Wed Apr  4 10:29:09 2018
@@ -289,8 +289,8 @@ Expected<DbiStream &> PDBFile::getPDBDbi
     auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
     if (!DbiS)
       return DbiS.takeError();
-    auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
-    if (auto EC = TempDbi->reload())
+    auto TempDbi = llvm::make_unique<DbiStream>(std::move(*DbiS));
+    if (auto EC = TempDbi->reload(this))
       return std::move(EC);
     Dbi = std::move(TempDbi);
   }

Modified: llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.cpp Wed Apr  4 10:29:09 2018
@@ -10,6 +10,7 @@
 #include "ExplainOutputStyle.h"
 
 #include "FormatUtil.h"
+#include "InputFile.h"
 #include "StreamUtil.h"
 #include "llvm-pdbutil.h"
 
@@ -19,6 +20,7 @@
 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryByteStream.h"
 #include "llvm/Support/BinaryStreamArray.h"
 #include "llvm/Support/Error.h"
 
@@ -27,114 +29,157 @@ using namespace llvm::codeview;
 using namespace llvm::msf;
 using namespace llvm::pdb;
 
-ExplainOutputStyle::ExplainOutputStyle(PDBFile &File, uint64_t FileOffset)
-    : File(File), FileOffset(FileOffset),
-      BlockIndex(FileOffset / File.getBlockSize()),
-      OffsetInBlock(FileOffset - BlockIndex * File.getBlockSize()),
-      P(2, false, outs()) {}
+ExplainOutputStyle::ExplainOutputStyle(InputFile &File, uint64_t FileOffset)
+    : File(File), FileOffset(FileOffset), P(2, false, outs()) {}
 
 Error ExplainOutputStyle::dump() {
   P.formatLine("Explaining file offset {0} of file '{1}'.", FileOffset,
                File.getFilePath());
 
-  bool IsAllocated = explainBlockStatus();
+  if (File.isPdb())
+    return explainPdbFile();
+
+  return explainBinaryFile();
+}
+
+Error ExplainOutputStyle::explainPdbFile() {
+  bool IsAllocated = explainPdbBlockStatus();
   if (!IsAllocated)
     return Error::success();
 
   AutoIndent Indent(P);
-  if (isSuperBlock())
-    explainSuperBlockOffset();
-  else if (isFpmBlock())
-    explainFpmBlockOffset();
-  else if (isBlockMapBlock())
-    explainBlockMapOffset();
-  else if (isStreamDirectoryBlock())
-    explainStreamDirectoryOffset();
-  else if (auto Index = getBlockStreamIndex())
-    explainStreamOffset(*Index);
+  if (isPdbSuperBlock())
+    explainPdbSuperBlockOffset();
+  else if (isPdbFpmBlock())
+    explainPdbFpmBlockOffset();
+  else if (isPdbBlockMapBlock())
+    explainPdbBlockMapOffset();
+  else if (isPdbStreamDirectoryBlock())
+    explainPdbStreamDirectoryOffset();
+  else if (auto Index = getPdbBlockStreamIndex())
+    explainPdbStreamOffset(*Index);
   else
-    explainUnknownBlock();
+    explainPdbUnknownBlock();
   return Error::success();
 }
 
-bool ExplainOutputStyle::isSuperBlock() const { return BlockIndex == 0; }
+Error ExplainOutputStyle::explainBinaryFile() {
+  std::unique_ptr<BinaryByteStream> Stream =
+      llvm::make_unique<BinaryByteStream>(File.unknown().getBuffer(),
+                                          llvm::support::little);
+  switch (opts::explain::InputType) {
+  case opts::explain::InputFileType::DBIStream: {
+    DbiStream Dbi(std::move(Stream));
+    if (auto EC = Dbi.reload(nullptr))
+      return EC;
+    explainStreamOffset(Dbi, FileOffset);
+    break;
+  }
+  case opts::explain::InputFileType::PDBStream: {
+    InfoStream Info(std::move(Stream));
+    if (auto EC = Info.reload())
+      return EC;
+    explainStreamOffset(Info, FileOffset);
+    break;
+  }
+  default:
+    llvm_unreachable("Invalid input file type!");
+  }
+  return Error::success();
+}
 
-bool ExplainOutputStyle::isFpm1() const {
-  return ((BlockIndex - 1) % File.getBlockSize() == 0);
+uint32_t ExplainOutputStyle::pdbBlockIndex() const {
+  return FileOffset / File.pdb().getBlockSize();
 }
-bool ExplainOutputStyle::isFpm2() const {
-  return ((BlockIndex - 2) % File.getBlockSize() == 0);
+
+uint32_t ExplainOutputStyle::pdbBlockOffset() const {
+  uint64_t BlockStart = pdbBlockIndex() * File.pdb().getBlockSize();
+  assert(FileOffset >= BlockStart);
+  return FileOffset - BlockStart;
+}
+
+bool ExplainOutputStyle::isPdbSuperBlock() const {
+  return pdbBlockIndex() == 0;
+}
+
+bool ExplainOutputStyle::isPdbFpm1() const {
+  return ((pdbBlockIndex() - 1) % File.pdb().getBlockSize() == 0);
+}
+bool ExplainOutputStyle::isPdbFpm2() const {
+  return ((pdbBlockIndex() - 2) % File.pdb().getBlockSize() == 0);
 }
 
-bool ExplainOutputStyle::isFpmBlock() const { return isFpm1() || isFpm2(); }
+bool ExplainOutputStyle::isPdbFpmBlock() const {
+  return isPdbFpm1() || isPdbFpm2();
+}
 
-bool ExplainOutputStyle::isBlockMapBlock() const {
-  return BlockIndex == File.getBlockMapIndex();
+bool ExplainOutputStyle::isPdbBlockMapBlock() const {
+  return pdbBlockIndex() == File.pdb().getBlockMapIndex();
 }
 
-bool ExplainOutputStyle::isStreamDirectoryBlock() const {
-  const auto &Layout = File.getMsfLayout();
-  return llvm::is_contained(Layout.DirectoryBlocks, BlockIndex);
+bool ExplainOutputStyle::isPdbStreamDirectoryBlock() const {
+  const auto &Layout = File.pdb().getMsfLayout();
+  return llvm::is_contained(Layout.DirectoryBlocks, pdbBlockIndex());
 }
 
-Optional<uint32_t> ExplainOutputStyle::getBlockStreamIndex() const {
-  const auto &Layout = File.getMsfLayout();
+Optional<uint32_t> ExplainOutputStyle::getPdbBlockStreamIndex() const {
+  const auto &Layout = File.pdb().getMsfLayout();
   for (const auto &Entry : enumerate(Layout.StreamMap)) {
-    if (!llvm::is_contained(Entry.value(), BlockIndex))
+    if (!llvm::is_contained(Entry.value(), pdbBlockIndex()))
       continue;
     return Entry.index();
   }
   return None;
 }
 
-bool ExplainOutputStyle::explainBlockStatus() {
-  if (FileOffset >= File.getFileSize()) {
+bool ExplainOutputStyle::explainPdbBlockStatus() {
+  if (FileOffset >= File.pdb().getFileSize()) {
     P.formatLine("Address {0} is not in the file (file size = {1}).",
-                 FileOffset, File.getFileSize());
+                 FileOffset, File.pdb().getFileSize());
     return false;
   }
-  P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, OffsetInBlock,
-               BlockIndex);
+  P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, pdbBlockOffset(),
+               pdbBlockIndex());
 
-  bool IsFree = File.getMsfLayout().FreePageMap[BlockIndex];
-  P.formatLine("Address is in block {0} ({1}allocated).", BlockIndex,
+  bool IsFree = File.pdb().getMsfLayout().FreePageMap[pdbBlockIndex()];
+  P.formatLine("Address is in block {0} ({1}allocated).", pdbBlockIndex(),
                IsFree ? "un" : "");
   return !IsFree;
 }
 
 #define endof(Class, Field) (offsetof(Class, Field) + sizeof(Class::Field))
 
-void ExplainOutputStyle::explainSuperBlockOffset() {
+void ExplainOutputStyle::explainPdbSuperBlockOffset() {
   P.formatLine("This corresponds to offset {0} of the MSF super block, ",
-               OffsetInBlock);
-  if (OffsetInBlock < endof(SuperBlock, MagicBytes))
+               pdbBlockOffset());
+  if (pdbBlockOffset() < endof(SuperBlock, MagicBytes))
     P.printLine("which is part of the MSF file magic.");
-  else if (OffsetInBlock < endof(SuperBlock, BlockSize)) {
+  else if (pdbBlockOffset() < endof(SuperBlock, BlockSize)) {
     P.printLine("which contains the block size of the file.");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->BlockSize));
-  } else if (OffsetInBlock < endof(SuperBlock, FreeBlockMapBlock)) {
+                 uint32_t(File.pdb().getMsfLayout().SB->BlockSize));
+  } else if (pdbBlockOffset() < endof(SuperBlock, FreeBlockMapBlock)) {
     P.printLine("which contains the index of the FPM block (e.g. 1 or 2).");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->FreeBlockMapBlock));
-  } else if (OffsetInBlock < endof(SuperBlock, NumBlocks)) {
+                 uint32_t(File.pdb().getMsfLayout().SB->FreeBlockMapBlock));
+  } else if (pdbBlockOffset() < endof(SuperBlock, NumBlocks)) {
     P.printLine("which contains the number of blocks in the file.");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->NumBlocks));
-  } else if (OffsetInBlock < endof(SuperBlock, NumDirectoryBytes)) {
+                 uint32_t(File.pdb().getMsfLayout().SB->NumBlocks));
+  } else if (pdbBlockOffset() < endof(SuperBlock, NumDirectoryBytes)) {
     P.printLine("which contains the number of bytes in the stream directory.");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->NumDirectoryBytes));
-  } else if (OffsetInBlock < endof(SuperBlock, Unknown1)) {
+                 uint32_t(File.pdb().getMsfLayout().SB->NumDirectoryBytes));
+  } else if (pdbBlockOffset() < endof(SuperBlock, Unknown1)) {
     P.printLine("whose purpose is unknown.");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->Unknown1));
-  } else if (OffsetInBlock < endof(SuperBlock, BlockMapAddr)) {
+                 uint32_t(File.pdb().getMsfLayout().SB->Unknown1));
+  } else if (pdbBlockOffset() < endof(SuperBlock, BlockMapAddr)) {
     P.printLine("which contains the file offset of the block map.");
     P.formatLine("The current value is {0}.",
-                 uint32_t(File.getMsfLayout().SB->BlockMapAddr));
+                 uint32_t(File.pdb().getMsfLayout().SB->BlockMapAddr));
   } else {
-    assert(OffsetInBlock > sizeof(SuperBlock));
+    assert(pdbBlockOffset() > sizeof(SuperBlock));
     P.printLine(
         "which is outside the range of valid data for the super block.");
   }
@@ -150,21 +195,21 @@ static std::string toBinaryString(uint8_
   return std::string(Result);
 }
 
-void ExplainOutputStyle::explainFpmBlockOffset() {
-  const MSFLayout &Layout = File.getMsfLayout();
+void ExplainOutputStyle::explainPdbFpmBlockOffset() {
+  const MSFLayout &Layout = File.pdb().getMsfLayout();
   uint32_t MainFpm = Layout.mainFpmBlock();
   uint32_t AltFpm = Layout.alternateFpmBlock();
 
-  assert(isFpmBlock());
-  uint32_t Fpm = isFpm1() ? 1 : 2;
-  uint32_t FpmChunk = BlockIndex / File.getBlockSize();
+  assert(isPdbFpmBlock());
+  uint32_t Fpm = isPdbFpm1() ? 1 : 2;
+  uint32_t FpmChunk = pdbBlockIndex() / File.pdb().getBlockSize();
   assert((Fpm == MainFpm) || (Fpm == AltFpm));
   (void)AltFpm;
   bool IsMain = (Fpm == MainFpm);
   P.formatLine("Address is in FPM{0} ({1} FPM)", Fpm, IsMain ? "Main" : "Alt");
   uint32_t DescribedBlockStart =
-      8 * (FpmChunk * File.getBlockSize() + OffsetInBlock);
-  if (DescribedBlockStart > File.getBlockCount()) {
+      8 * (FpmChunk * File.pdb().getBlockSize() + pdbBlockOffset());
+  if (DescribedBlockStart > File.pdb().getBlockCount()) {
     P.printLine("Address is in extraneous FPM space.");
     return;
   }
@@ -172,13 +217,13 @@ void ExplainOutputStyle::explainFpmBlock
   P.formatLine("Address describes the allocation status of blocks [{0},{1})",
                DescribedBlockStart, DescribedBlockStart + 8);
   ArrayRef<uint8_t> Bytes;
-  cantFail(File.getMsfBuffer().readBytes(FileOffset, 1, Bytes));
+  cantFail(File.pdb().getMsfBuffer().readBytes(FileOffset, 1, Bytes));
   P.formatLine("Status = {0} (Note: 0 = allocated, 1 = free)",
                toBinaryString(Bytes[0]));
 }
 
-void ExplainOutputStyle::explainBlockMapOffset() {
-  uint64_t BlockMapOffset = File.getBlockMapOffset();
+void ExplainOutputStyle::explainPdbBlockMapOffset() {
+  uint64_t BlockMapOffset = File.pdb().getBlockMapOffset();
   uint32_t OffsetInBlock = FileOffset - BlockMapOffset;
   P.formatLine("Address is at offset {0} of the directory block list",
                OffsetInBlock);
@@ -195,25 +240,29 @@ static uint32_t getOffsetInStream(ArrayR
   return StreamBlockIndex * BlockSize + OffsetInBlock;
 }
 
-void ExplainOutputStyle::explainStreamOffset(uint32_t Stream) {
+void ExplainOutputStyle::explainPdbStreamOffset(uint32_t Stream) {
   SmallVector<StreamInfo, 12> Streams;
-  discoverStreamPurposes(File, Streams);
+  discoverStreamPurposes(File.pdb(), Streams);
 
   assert(Stream <= Streams.size());
   const StreamInfo &S = Streams[Stream];
-  const auto &Layout = File.getStreamLayout(Stream);
+  const auto &Layout = File.pdb().getStreamLayout(Stream);
   uint32_t StreamOff =
-      getOffsetInStream(Layout.Blocks, FileOffset, File.getBlockSize());
+      getOffsetInStream(Layout.Blocks, FileOffset, File.pdb().getBlockSize());
   P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.",
                StreamOff, Layout.Length, Stream, S.getLongName(),
                (StreamOff > Layout.Length) ? " in unused space" : "");
   switch (S.getPurpose()) {
-  case StreamPurpose::DBI:
-    explainDbiStream(Stream, StreamOff);
+  case StreamPurpose::DBI: {
+    DbiStream &Dbi = cantFail(File.pdb().getPDBDbiStream());
+    explainStreamOffset(Dbi, StreamOff);
     break;
-  case StreamPurpose::PDB:
-    explainPdbStream(Stream, StreamOff);
+  }
+  case StreamPurpose::PDB: {
+    InfoStream &Info = cantFail(File.pdb().getPDBInfoStream());
+    explainStreamOffset(Info, StreamOff);
     break;
+  }
   case StreamPurpose::IPI:
   case StreamPurpose::TPI:
   case StreamPurpose::ModuleStream:
@@ -223,11 +272,11 @@ void ExplainOutputStyle::explainStreamOf
   }
 }
 
-void ExplainOutputStyle::explainStreamDirectoryOffset() {
-  auto DirectoryBlocks = File.getDirectoryBlockArray();
-  const auto &Layout = File.getMsfLayout();
+void ExplainOutputStyle::explainPdbStreamDirectoryOffset() {
+  auto DirectoryBlocks = File.pdb().getDirectoryBlockArray();
+  const auto &Layout = File.pdb().getMsfLayout();
   uint32_t StreamOff =
-      getOffsetInStream(DirectoryBlocks, FileOffset, File.getBlockSize());
+      getOffsetInStream(DirectoryBlocks, FileOffset, File.pdb().getBlockSize());
   P.formatLine("Address is at offset {0}/{1} of Stream Directory{2}.",
                StreamOff, uint32_t(Layout.SB->NumDirectoryBytes),
                uint32_t(StreamOff > Layout.SB->NumDirectoryBytes)
@@ -235,7 +284,7 @@ void ExplainOutputStyle::explainStreamDi
                    : "");
 }
 
-void ExplainOutputStyle::explainUnknownBlock() {
+void ExplainOutputStyle::explainPdbUnknownBlock() {
   P.formatLine("Address has unknown purpose.");
 }
 
@@ -352,10 +401,9 @@ static void explainSubstreamOffset(LineP
   }
 }
 
-void ExplainOutputStyle::explainDbiStream(uint32_t StreamIdx,
-                                          uint32_t OffsetInStream) {
+void ExplainOutputStyle::explainStreamOffset(DbiStream &Dbi,
+                                             uint32_t OffsetInStream) {
   P.printLine("Within the DBI stream:");
-  DbiStream &Dbi = cantFail(File.getPDBDbiStream());
   AutoIndent Indent(P);
   const DbiStreamHeader *Header = Dbi.getHeader();
   assert(Header != nullptr);
@@ -401,10 +449,9 @@ static void explainPdbStreamHeaderOffset
     printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid));
 }
 
-void ExplainOutputStyle::explainPdbStream(uint32_t StreamIdx,
-                                          uint32_t OffsetInStream) {
+void ExplainOutputStyle::explainStreamOffset(InfoStream &Info,
+                                             uint32_t OffsetInStream) {
   P.printLine("Within the PDB stream:");
-  InfoStream &Info = cantFail(File.getPDBInfoStream());
   AutoIndent Indent(P);
 
   struct SubstreamInfo {

Modified: llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/ExplainOutputStyle.h Wed Apr  4 10:29:09 2018
@@ -20,41 +20,46 @@ namespace llvm {
 namespace pdb {
 
 class DbiStream;
-class PDBFile;
+class InfoStream;
+class InputFile;
 
 class ExplainOutputStyle : public OutputStyle {
 
 public:
-  ExplainOutputStyle(PDBFile &File, uint64_t FileOffset);
+  ExplainOutputStyle(InputFile &File, uint64_t FileOffset);
 
   Error dump() override;
 
 private:
-  bool explainBlockStatus();
+  Error explainPdbFile();
+  Error explainBinaryFile();
 
-  bool isFpm1() const;
-  bool isFpm2() const;
+  bool explainPdbBlockStatus();
 
-  bool isSuperBlock() const;
-  bool isFpmBlock() const;
-  bool isBlockMapBlock() const;
-  bool isStreamDirectoryBlock() const;
-  Optional<uint32_t> getBlockStreamIndex() const;
-
-  void explainSuperBlockOffset();
-  void explainFpmBlockOffset();
-  void explainBlockMapOffset();
-  void explainStreamDirectoryOffset();
-  void explainStreamOffset(uint32_t Stream);
-  void explainUnknownBlock();
+  bool isPdbFpm1() const;
+  bool isPdbFpm2() const;
 
-  void explainDbiStream(uint32_t StreamIdx, uint32_t OffsetInStream);
-  void explainPdbStream(uint32_t StreamIdx, uint32_t OffsetInStream);
+  bool isPdbSuperBlock() const;
+  bool isPdbFpmBlock() const;
+  bool isPdbBlockMapBlock() const;
+  bool isPdbStreamDirectoryBlock() const;
+  Optional<uint32_t> getPdbBlockStreamIndex() const;
+
+  void explainPdbSuperBlockOffset();
+  void explainPdbFpmBlockOffset();
+  void explainPdbBlockMapOffset();
+  void explainPdbStreamDirectoryOffset();
+  void explainPdbStreamOffset(uint32_t Stream);
+  void explainPdbUnknownBlock();
 
-  PDBFile &File;
+  void explainStreamOffset(DbiStream &Stream, uint32_t OffsetInStream);
+  void explainStreamOffset(InfoStream &Stream, uint32_t OffsetInStream);
+
+  uint32_t pdbBlockIndex() const;
+  uint32_t pdbBlockOffset() const;
+
+  InputFile &File;
   const uint64_t FileOffset;
-  const uint64_t BlockIndex;
-  const uint64_t OffsetInBlock;
   LinePrinter P;
 };
 } // namespace pdb

Modified: llvm/trunk/tools/llvm-pdbutil/InputFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/InputFile.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/InputFile.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/InputFile.cpp Wed Apr  4 10:29:09 2018
@@ -242,7 +242,7 @@ void SymbolGroup::formatFromChecksumsOff
   }
 }
 
-Expected<InputFile> InputFile::open(StringRef Path) {
+Expected<InputFile> InputFile::open(StringRef Path, bool AllowUnknownFile) {
   InputFile IF;
   if (!llvm::sys::fs::exists(Path))
     return make_error<StringError>(formatv("File {0} not found", Path),
@@ -274,9 +274,19 @@ Expected<InputFile> InputFile::open(Stri
     return std::move(IF);
   }
 
-  return make_error<StringError>(
-      formatv("File {0} is not a supported file type", Path),
-      inconvertibleErrorCode());
+  if (!AllowUnknownFile)
+    return make_error<StringError>(
+        formatv("File {0} is not a supported file type", Path),
+        inconvertibleErrorCode());
+
+  auto Result = MemoryBuffer::getFile(Path, -1i64, false);
+  if (!Result)
+    return make_error<StringError>(
+        formatv("File {0} could not be opened", Path), Result.getError());
+
+  IF.UnknownFile = std::move(*Result);
+  IF.PdbOrObj = IF.UnknownFile.get();
+  return std::move(IF);
 }
 
 PDBFile &InputFile::pdb() {
@@ -299,6 +309,25 @@ const object::COFFObjectFile &InputFile:
   return *PdbOrObj.get<object::COFFObjectFile *>();
 }
 
+MemoryBuffer &InputFile::unknown() {
+  assert(isUnknown());
+  return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+const MemoryBuffer &InputFile::unknown() const {
+  assert(isUnknown());
+  return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+StringRef InputFile::getFilePath() const {
+  if (isPdb())
+    return pdb().getFilePath();
+  if (isObj())
+    return obj().getFileName();
+  assert(isUnknown());
+  return unknown().getBufferIdentifier();
+}
+
 bool InputFile::hasTypes() const {
   if (isPdb())
     return pdb().hasPDBTpiStream();
@@ -323,6 +352,8 @@ bool InputFile::isObj() const {
   return PdbOrObj.is<object::COFFObjectFile *>();
 }
 
+bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); }
+
 codeview::LazyRandomTypeCollection &
 InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) {
   if (Types && Kind == kTypes)

Modified: llvm/trunk/tools/llvm-pdbutil/InputFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/InputFile.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/InputFile.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/InputFile.h Wed Apr  4 10:29:09 2018
@@ -43,7 +43,8 @@ class InputFile {
 
   std::unique_ptr<NativeSession> PdbSession;
   object::OwningBinary<object::Binary> CoffObject;
-  PointerUnion<PDBFile *, object::COFFObjectFile *> PdbOrObj;
+  std::unique_ptr<MemoryBuffer> UnknownFile;
+  PointerUnion3<PDBFile *, object::COFFObjectFile *, MemoryBuffer *> PdbOrObj;
 
   using TypeCollectionPtr = std::unique_ptr<codeview::LazyRandomTypeCollection>;
 
@@ -58,12 +59,17 @@ public:
   ~InputFile();
   InputFile(InputFile &&Other) = default;
 
-  static Expected<InputFile> open(StringRef Path);
+  static Expected<InputFile> open(StringRef Path,
+                                  bool AllowUnknownFile = false);
 
   PDBFile &pdb();
   const PDBFile &pdb() const;
   object::COFFObjectFile &obj();
   const object::COFFObjectFile &obj() const;
+  MemoryBuffer &unknown();
+  const MemoryBuffer &unknown() const;
+
+  StringRef getFilePath() const;
 
   bool hasTypes() const;
   bool hasIds() const;
@@ -77,6 +83,7 @@ public:
 
   bool isPdb() const;
   bool isObj() const;
+  bool isUnknown() const;
 };
 
 class SymbolGroup {

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Wed Apr  4 10:29:09 2018
@@ -621,6 +621,20 @@ cl::list<std::string> InputFilename(cl::
 
 cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
                            cl::sub(ExplainSubcommand), cl::OneOrMore);
+
+cl::opt<InputFileType> InputType(
+    "input-type", cl::desc("Specify how to interpret the input file"),
+    cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
+    cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
+                          "Treat input as a PDB file (default)"),
+               clEnumValN(InputFileType::PDBStream, "pdb-stream",
+                          "Treat input as raw contents of PDB stream"),
+               clEnumValN(InputFileType::DBIStream, "dbi-stream",
+                          "Treat input as raw contents of DBI stream"),
+               clEnumValN(InputFileType::Names, "names-stream",
+                          "Treat input as raw contents of /names named stream"),
+               clEnumValN(InputFileType::ModuleStream, "mod-stream",
+                          "Treat input as raw contents of a module stream")));
 } // namespace explain
 
 namespace exportstream {
@@ -772,7 +786,6 @@ static void pdb2Yaml(StringRef Path) {
 }
 
 static void dumpRaw(StringRef Path) {
-
   InputFile IF = ExitOnErr(InputFile::open(Path));
 
   auto O = llvm::make_unique<DumpOutputStyle>(IF);
@@ -1111,10 +1124,11 @@ static void mergePdbs() {
 
 static void explain() {
   std::unique_ptr<IPDBSession> Session;
-  PDBFile &File = loadPDB(opts::explain::InputFilename.front(), Session);
+  InputFile IF =
+      ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
 
   for (uint64_t Off : opts::explain::Offsets) {
-    auto O = llvm::make_unique<ExplainOutputStyle>(File, Off);
+    auto O = llvm::make_unique<ExplainOutputStyle>(IF, Off);
 
     ExitOnErr(O->dump());
   }

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=329207&r1=329206&r2=329207&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Wed Apr  4 10:29:09 2018
@@ -190,8 +190,11 @@ extern llvm::cl::opt<bool> DumpModuleSym
 } // namespace pdb2yaml
 
 namespace explain {
+enum class InputFileType { PDBFile, PDBStream, DBIStream, Names, ModuleStream };
+
 extern llvm::cl::list<std::string> InputFilename;
 extern llvm::cl::list<uint64_t> Offsets;
+extern llvm::cl::opt<InputFileType> InputType;
 } // namespace explain
 
 namespace exportstream {




More information about the llvm-commits mailing list