[PDB] Add an explain subcommand.

When investigating various things, we often have a file offset
and what to know what's in the PDB at that address.  For example
we may be doing a binary comparison of two LLD-generated PDBs
to look for sources of non-determinism, or we may wish to compare
an LLD-generated PDB with a Microsoft generated PDB for sources
of byte-for-byte incompatibility.  In these cases, we can do a
binary diff of the two files, and once we find a mismatched byte
we can use explain to figure out what that byte is, immediately
honining in on the problem.

This patch implements this by trying to narrow the meaning of
a particular file offset down as much as possible.

Differential Revision: https://reviews.llvm.org/D44959

llvm-svn: 328799
diff --git a/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h b/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
new file mode 100644
index 0000000..386f615
--- /dev/null
+++ b/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
@@ -0,0 +1,59 @@
+//===- ExplainOutputStyle.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_EXPLAINOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_EXPLAINOUTPUTSTYLE_H
+
+#include "LinePrinter.h"
+#include "OutputStyle.h"
+
+#include <string>
+
+namespace llvm {
+
+namespace pdb {
+
+class PDBFile;
+
+class ExplainOutputStyle : public OutputStyle {
+
+public:
+  ExplainOutputStyle(PDBFile &File, uint64_t FileOffset);
+
+  Error dump() override;
+
+private:
+  bool explainBlockStatus();
+
+  bool isFpm1() const;
+  bool isFpm2() const;
+
+  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();
+
+  PDBFile &File;
+  const uint64_t FileOffset;
+  const uint64_t BlockIndex;
+  const uint64_t OffsetInBlock;
+  LinePrinter P;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif