[llvm] r297983 - [llvm-pdbdump] Add support for diffing the PDB Stream.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 16 13:18:41 PDT 2017


Author: zturner
Date: Thu Mar 16 15:18:41 2017
New Revision: 297983

URL: http://llvm.org/viewvc/llvm-project?rev=297983&view=rev
Log:
[llvm-pdbdump] Add support for diffing the PDB Stream.

In doing so I discovered that we completely ignore some bytes
of the PDB Stream after we "finish" loading it.  These bytes
seem to specify some additional information about what kind
of data is present in the PDB.  A subsequent patch will add
code to read in those fields and store their values.

Added:
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/Formatters.h
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/Formatters.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
    llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
    llvm/trunk/tools/llvm-pdbdump/Diff.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/Formatters.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/Formatters.h?rev=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/Formatters.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/Formatters.h Thu Mar 16 15:18:41 2017
@@ -30,6 +30,10 @@ public:
 inline detail::GuidAdapter fmt_guid(StringRef Item) {
   return detail::GuidAdapter(Item);
 }
+
+inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) {
+  return detail::GuidAdapter(Item);
+}
 }
 }
 

Added: llvm/trunk/include/llvm/DebugInfo/PDB/Native/Formatters.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/Formatters.h?rev=297983&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/Formatters.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/Formatters.h Thu Mar 16 15:18:41 2017
@@ -0,0 +1,52 @@
+//===- Formatters.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_DEBUGINFO_PDB_NATIVE_FORMATTERS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_FORMATTERS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/FormatProviders.h"
+
+#define FORMAT_CASE(Value, Name)                                               \
+  case Value:                                                                  \
+    Stream << Name;                                                            \
+    break;
+
+namespace llvm {
+template <> struct format_provider<pdb::PDB_UniqueId> {
+  static void format(const pdb::PDB_UniqueId &V, llvm::raw_ostream &Stream,
+                     StringRef Style) {
+    codeview::fmt_guid(V.Guid).format(Stream, Style);
+  }
+};
+
+template <> struct format_provider<pdb::PdbRaw_ImplVer> {
+  static void format(const pdb::PdbRaw_ImplVer &V, llvm::raw_ostream &Stream,
+                     StringRef Style) {
+    switch (V) {
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC110, "VC110")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC140, "VC140")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC2, "VC2")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC4, "VC4")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC41, "VC41")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC50, "VC50")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70, "VC70")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70Dep, "VC70Dep")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC80, "VC80")
+      FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC98, "VC98")
+    }
+  }
+};
+}
+
+#endif

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=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/InfoStream.h Thu Mar 16 15:18:41 2017
@@ -32,10 +32,13 @@ public:
 
   Error reload();
 
+  uint32_t getStreamSize() const;
+
   PdbRaw_ImplVer getVersion() const;
   uint32_t getSignature() const;
   uint32_t getAge() const;
   PDB_UniqueId getGuid() const;
+  uint32_t getNamedStreamMapByteSize() const;
 
   const NamedStreamMap &getNamedStreams() const;
 
@@ -63,6 +66,8 @@ private:
   // universally unique.
   PDB_UniqueId Guid;
 
+  uint32_t NamedStreamMapByteSize = 0;
+
   NamedStreamMap NamedStreams;
 };
 }

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h?rev=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h Thu Mar 16 15:18:41 2017
@@ -36,6 +36,7 @@ public:
   Error commit(BinaryStreamWriter &Writer) const;
   uint32_t finalize();
 
+  uint32_t size() const;
   bool get(StringRef Stream, uint32_t &StreamNo) const;
   void set(StringRef Stream, uint32_t StreamNo);
   void remove(StringRef Stream);

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=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h Thu Mar 16 15:18:41 2017
@@ -266,6 +266,10 @@ struct PDB_UniqueId {
   uint8_t Guid[16];
 };
 
+inline bool operator==(const PDB_UniqueId &LHS, const PDB_UniqueId &RHS) {
+  return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid));
+}
+
 // The header preceeding the global TPI stream.
 // This corresponds to `HDR` in PDB/dbi/tpi.h.
 struct TpiStreamHeader {

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=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/InfoStream.cpp Thu Mar 16 15:18:41 2017
@@ -51,9 +51,16 @@ Error InfoStream::reload() {
   Age = H->Age;
   Guid = H->Guid;
 
-  return NamedStreams.load(Reader);
+  uint32_t Offset = Reader.getOffset();
+  if (auto EC = NamedStreams.load(Reader))
+    return EC;
+  uint32_t NewOffset = Reader.getOffset();
+  NamedStreamMapByteSize = NewOffset - Offset;
+  return Error::success();
 }
 
+uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
+
 uint32_t InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
   uint32_t Result;
   if (!NamedStreams.get(Name, Result))
@@ -76,6 +83,10 @@ uint32_t InfoStream::getAge() const { re
 
 PDB_UniqueId InfoStream::getGuid() const { return Guid; }
 
+uint32_t InfoStream::getNamedStreamMapByteSize() const {
+  return NamedStreamMapByteSize;
+}
+
 const NamedStreamMap &InfoStream::getNamedStreams() const {
   return NamedStreams;
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp?rev=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp Thu Mar 16 15:18:41 2017
@@ -114,6 +114,8 @@ NamedStreamMap::entries() const {
                                                       Mapping.end());
 }
 
+uint32_t NamedStreamMap::size() const { return Mapping.size(); }
+
 bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
   auto Iter = Mapping.find(Stream);
   if (Iter == Mapping.end())

Modified: llvm/trunk/tools/llvm-pdbdump/Diff.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/Diff.cpp?rev=297983&r1=297982&r2=297983&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/Diff.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/Diff.cpp Thu Mar 16 15:18:41 2017
@@ -12,6 +12,8 @@
 #include "StreamUtil.h"
 #include "llvm-pdbdump.h"
 
+#include "llvm/DebugInfo/PDB/Native/Formatters.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
 #include "llvm/DebugInfo/PDB/Native/StringTable.h"
@@ -114,12 +116,37 @@ Error DiffStyle::dump() {
 template <typename T>
 static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1,
                          T V2) {
-  if (V1 != V2) {
-    outs().indent(2) << Label << "\n";
-    outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1);
-    outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2);
+  if (V1 == V2) {
+    outs() << formatv("  {0}: No differences detected!\n", Label);
+    return false;
   }
-  return (V1 != V2);
+
+  outs().indent(2) << Label << "\n";
+  outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1);
+  outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2);
+  return true;
+}
+
+template <typename T>
+static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2,
+                                      T &&OnlyRange1, T &&OnlyRange2,
+                                      StringRef Label) {
+  bool HasDiff = false;
+  if (!OnlyRange1.empty()) {
+    HasDiff = true;
+    outs() << formatv("  {0} {1}(s) only in ({2})\n", OnlyRange1.size(), Label,
+                      File1.getFilePath());
+    for (const auto &Item : OnlyRange1)
+      outs() << formatv("    {0}\n", Label, Item);
+  }
+  if (!OnlyRange2.empty()) {
+    HasDiff = true;
+    outs() << formatv("  {0} {1}(s) only in ({2})\n", OnlyRange2.size(),
+                      File2.getFilePath());
+    for (const auto &Item : OnlyRange2)
+      outs() << formatv("    {0}\n", Item);
+  }
+  return HasDiff;
 }
 
 Error DiffStyle::diffSuperBlock() {
@@ -299,8 +326,16 @@ Error DiffStyle::diffStringTable() {
   auto &ST1 = *ExpectedST1;
   auto &ST2 = *ExpectedST2;
 
-  HasDiff |= diffAndPrint("Stream Size", File1, File2, ST1.getByteSize(),
-                          ST2.getByteSize());
+  if (ST1.getByteSize() != ST2.getByteSize()) {
+    outs() << "  Stream Size\n";
+    outs() << formatv("    {0} - {1} byte(s)\n", File1.getFilePath(),
+                      ST1.getByteSize());
+    outs() << formatv("    {0} - {1} byte(s)\n", File2.getFilePath(),
+                      ST2.getByteSize());
+    outs() << formatv("    Difference: {0} bytes\n",
+                      AbsoluteDifference(ST1.getByteSize(), ST2.getByteSize()));
+    HasDiff = true;
+  }
   HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(),
                           ST1.getHashVersion());
   HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(),
@@ -351,22 +386,21 @@ Error DiffStyle::diffStringTable() {
 
     SmallVector<StringRef, 64> OnlyP;
     SmallVector<StringRef, 64> OnlyQ;
-
+    auto End1 = std::remove(Strings1.begin(), Strings1.end(), "");
+    auto End2 = std::remove(Strings2.begin(), Strings2.end(), "");
+    uint32_t Empty1 = std::distance(End1, Strings1.end());
+    uint32_t Empty2 = std::distance(End2, Strings2.end());
+    Strings1.erase(End1, Strings1.end());
+    Strings2.erase(End2, Strings2.end());
     set_differences(Strings1, Strings2, &OnlyP, &OnlyQ);
+    printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String");
 
-    if (!OnlyP.empty()) {
-      HasDiff = true;
-      outs() << formatv("  {0} String(s) only in ({1})\n", OnlyP.size(),
-                        File1.getFilePath());
-      for (auto Item : OnlyP)
-        outs() << formatv("    {2}\n", Item);
-    }
-    if (!OnlyQ.empty()) {
-      HasDiff = true;
-      outs() << formatv("  {0} String(s) only in ({1})\n", OnlyQ.size(),
-                        File2.getFilePath());
-      for (auto Item : OnlyQ)
-        outs() << formatv("    {2}\n", Item);
+    if (Empty1 != Empty2) {
+      PDBFile &MoreF = (Empty1 > Empty2) ? File1 : File2;
+      PDBFile &LessF = (Empty1 < Empty2) ? File1 : File2;
+      uint32_t Difference = AbsoluteDifference(Empty1, Empty2);
+      outs() << formatv("  {0} had {1} more empty strings than {2}\n",
+                        MoreF.getFilePath(), Difference, LessF.getFilePath());
     }
   }
   if (!HasDiff)
@@ -376,7 +410,60 @@ Error DiffStyle::diffStringTable() {
 
 Error DiffStyle::diffFreePageMap() { return Error::success(); }
 
-Error DiffStyle::diffInfoStream() { return Error::success(); }
+Error DiffStyle::diffInfoStream() {
+  auto ExpectedInfo1 = File1.getPDBInfoStream();
+  auto ExpectedInfo2 = File2.getPDBInfoStream();
+
+  outs() << "PDB Stream: Searching for differences...\n";
+  bool Has1 = !!ExpectedInfo1;
+  bool Has2 = !!ExpectedInfo2;
+  if (!(Has1 && Has2)) {
+    if (Has1 != Has2)
+      outs() << formatv("{0} does not have a PDB Stream!\n",
+                        Has1 ? File1.getFilePath() : File2.getFilePath());
+    consumeError(ExpectedInfo2.takeError());
+    consumeError(ExpectedInfo2.takeError());
+    return Error::success();
+  }
+
+  bool HasDiff = false;
+  auto &IS1 = *ExpectedInfo1;
+  auto &IS2 = *ExpectedInfo2;
+  if (IS1.getStreamSize() != IS2.getStreamSize()) {
+    outs() << "  Stream Size\n";
+    outs() << formatv("    {0} - {1} byte(s)\n", File1.getFilePath(),
+                      IS1.getStreamSize());
+    outs() << formatv("    {0} - {1} byte(s)\n", File2.getFilePath(),
+                      IS2.getStreamSize());
+    outs() << formatv(
+        "    Difference: {0} bytes\n",
+        AbsoluteDifference(IS1.getStreamSize(), IS2.getStreamSize()));
+    HasDiff = true;
+  }
+  HasDiff |= diffAndPrint("Age", File1, File2, IS1.getAge(), IS2.getAge());
+  HasDiff |= diffAndPrint("Guid", File1, File2, IS1.getGuid(), IS2.getGuid());
+  HasDiff |= diffAndPrint("Signature", File1, File2, IS1.getSignature(),
+                          IS2.getSignature());
+  HasDiff |=
+      diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion());
+  HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2,
+                          IS1.getNamedStreamMapByteSize(),
+                          IS2.getNamedStreamMapByteSize());
+  SmallVector<StringRef, 4> NS1;
+  SmallVector<StringRef, 4> NS2;
+  for (const auto &X : IS1.getNamedStreams().entries())
+    NS1.push_back(X.getKey());
+  for (const auto &X : IS2.getNamedStreams().entries())
+    NS2.push_back(X.getKey());
+  SmallVector<StringRef, 4> OnlyP;
+  SmallVector<StringRef, 4> OnlyQ;
+  set_differences(NS1, NS2, &OnlyP, &OnlyQ);
+  printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "Named Streams");
+  if (!HasDiff)
+    outs() << "PDB Stream: No differences detected!\n";
+
+  return Error::success();
+}
 
 Error DiffStyle::diffDbiStream() { return Error::success(); }
 




More information about the llvm-commits mailing list