[llvm] r297901 - [llvm-pdbdump] Add support for diffing the String Table.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 15 15:19:30 PDT 2017


Author: zturner
Date: Wed Mar 15 17:19:30 2017
New Revision: 297901

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

Modified:
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTable.h
    llvm/trunk/lib/DebugInfo/PDB/Native/StringTable.cpp
    llvm/trunk/tools/llvm-pdbdump/Diff.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTable.h?rev=297901&r1=297900&r2=297901&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTable.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTable.h Wed Mar 15 17:19:30 2017
@@ -30,6 +30,8 @@ public:
 
   Error load(BinaryStreamReader &Stream);
 
+  uint32_t getByteSize() const;
+
   uint32_t getNameCount() const { return NameCount; }
   uint32_t getHashVersion() const { return HashVersion; }
   uint32_t getSignature() const { return Signature; }
@@ -42,9 +44,10 @@ public:
 private:
   BinaryStreamRef NamesBuffer;
   FixedStreamArray<support::ulittle32_t> IDs;
-  uint32_t Signature;
-  uint32_t HashVersion;
-  uint32_t NameCount;
+  uint32_t ByteSize = 0;
+  uint32_t Signature = 0;
+  uint32_t HashVersion = 0;
+  uint32_t NameCount = 0;
 };
 
 } // end namespace pdb

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/StringTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/StringTable.cpp?rev=297901&r1=297900&r2=297901&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/StringTable.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/StringTable.cpp Wed Mar 15 17:19:30 2017
@@ -20,9 +20,11 @@ using namespace llvm;
 using namespace llvm::support;
 using namespace llvm::pdb;
 
-StringTable::StringTable() : Signature(0), HashVersion(0), NameCount(0) {}
+StringTable::StringTable() {}
 
 Error StringTable::load(BinaryStreamReader &Stream) {
+  ByteSize = Stream.getLength();
+
   const StringTableHeader *H;
   if (auto EC = Stream.readObject(H))
     return EC;
@@ -56,9 +58,18 @@ Error StringTable::load(BinaryStreamRead
 
   if (auto EC = Stream.readInteger(NameCount))
     return EC;
+
+  if (Stream.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::stream_too_long,
+      "Unexpected bytes found in string table");
+
   return Error::success();
 }
 
+uint32_t StringTable::getByteSize() const {
+  return ByteSize;
+}
+
 StringRef StringTable::getStringForID(uint32_t ID) const {
   if (ID == IDs[0])
     return StringRef();

Modified: llvm/trunk/tools/llvm-pdbdump/Diff.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/Diff.cpp?rev=297901&r1=297900&r2=297901&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/Diff.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/Diff.cpp Wed Mar 15 17:19:30 2017
@@ -14,6 +14,7 @@
 
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/StringTable.h"
 
 #include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -21,6 +22,48 @@
 using namespace llvm;
 using namespace llvm::pdb;
 
+template<typename R>
+using ValueOfRange = llvm::detail::ValueOfRange<R>;
+
+template<typename Range, typename Comp>
+static void set_differences(Range &&R1, Range &&R2,
+    SmallVectorImpl<ValueOfRange<Range>> *OnlyLeft,
+    SmallVectorImpl<ValueOfRange<Range>> *OnlyRight,
+    SmallVectorImpl<ValueOfRange<Range>> *Intersection, Comp Comparator) {
+
+  std::sort(R1.begin(), R1.end(), Comparator);
+  std::sort(R2.begin(), R2.end(), Comparator);
+
+  if (OnlyLeft) {
+    OnlyLeft->reserve(R1.size());
+    auto End = std::set_difference(R1.begin(), R1.end(), R2.begin(), R2.end(),
+      OnlyLeft->begin(), Comparator);
+    OnlyLeft->set_size(std::distance(OnlyLeft->begin(), End));
+  }
+  if (OnlyRight) {
+    OnlyLeft->reserve(R2.size());
+    auto End = std::set_difference(R2.begin(), R2.end(), R1.begin(), R1.end(),
+      OnlyRight->begin(), Comparator);
+    OnlyRight->set_size(std::distance(OnlyRight->begin(), End));
+  }
+  if (Intersection) {
+    Intersection->reserve(std::min(R1.size(), R2.size()));
+    auto End = std::set_intersection(R1.begin(), R1.end(), R2.begin(),
+      R2.end(), Intersection->begin(), Comparator);
+    Intersection->set_size(std::distance(Intersection->begin(), End));
+  }
+}
+
+template<typename Range>
+static void set_differences(Range &&R1, Range &&R2,
+  SmallVectorImpl<ValueOfRange<Range>> *OnlyLeft,
+  SmallVectorImpl<ValueOfRange<Range>> *OnlyRight,
+  SmallVectorImpl<ValueOfRange<Range>> *Intersection) {
+  std::less<ValueOfRange<Range>> Comp;
+  set_differences(std::forward<Range>(R1), std::forward<Range>(R2), OnlyLeft, OnlyRight, Intersection, Comp);
+}
+
+
 DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2)
     : File1(File1), File2(File2) {}
 
@@ -162,26 +205,12 @@ Error DiffStyle::diffStreamDirectory() {
     auto Comparator = [](const value_type &I1, const value_type &I2) {
       return I1.value() < I2.value();
     };
-    std::sort(PI.begin(), PI.end(), Comparator);
-    std::sort(QI.begin(), QI.end(), Comparator);
 
     decltype(PI) OnlyP;
     decltype(QI) OnlyQ;
     decltype(PI) Common;
 
-    OnlyP.reserve(P.size());
-    OnlyQ.reserve(Q.size());
-    Common.reserve(Q.size());
-
-    auto PEnd = std::set_difference(PI.begin(), PI.end(), QI.begin(), QI.end(),
-                                    OnlyP.begin(), Comparator);
-    auto QEnd = std::set_difference(QI.begin(), QI.end(), PI.begin(), PI.end(),
-                                    OnlyQ.begin(), Comparator);
-    auto ComEnd = std::set_intersection(PI.begin(), PI.end(), QI.begin(),
-                                        QI.end(), Common.begin(), Comparator);
-    OnlyP.set_size(std::distance(OnlyP.begin(), PEnd));
-    OnlyQ.set_size(std::distance(OnlyQ.begin(), QEnd));
-    Common.set_size(std::distance(Common.begin(), ComEnd));
+    set_differences(PI, QI, &OnlyP, &OnlyQ, &Common, Comparator);
 
     if (!OnlyP.empty()) {
       HasDifferences = true;
@@ -238,7 +267,98 @@ Error DiffStyle::diffStreamDirectory() {
   return Error::success();
 }
 
-Error DiffStyle::diffStringTable() { return Error::success(); }
+Error DiffStyle::diffStringTable() {
+  auto ExpectedST1 = File1.getStringTable();
+  auto ExpectedST2 = File2.getStringTable();
+  outs() << "String Table: Searching for differences...\n";
+  bool Has1 = !!ExpectedST1;
+  bool Has2 = !!ExpectedST2;
+  if (!(Has1 && Has2)) {
+    // If one has a string table and the other doesn't, we can print less output.
+    if (Has1 != Has2) {
+      if (Has1) {
+        outs() << formatv("  {0}: ({1} strings)\n", File1.getFilePath(), ExpectedST1->getNameCount());
+        outs() << formatv("  {0}: (string table not present)\n", File2.getFilePath());
+      } else {
+        outs() << formatv("  {0}: (string table not present)\n", File1.getFilePath());
+        outs() << formatv("  {0}: ({1})\n", File2.getFilePath(), ExpectedST2->getNameCount());
+      }
+    }
+    consumeError(ExpectedST1.takeError());
+    consumeError(ExpectedST2.takeError());
+    return Error::success();
+  }
+
+  bool HasDiff = false;
+  auto &ST1 = *ExpectedST1;
+  auto &ST2 = *ExpectedST2;
+
+  HasDiff |= diffAndPrint("Stream Size", File1, File2, ST1.getByteSize(), ST2.getByteSize());
+  HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(), ST1.getHashVersion());
+  HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(), ST1.getSignature());
+
+  // Both have a valid string table, dive in and compare individual strings.
+
+  auto IdList1 = ST1.name_ids();
+  auto IdList2 = ST2.name_ids();
+  if (opts::diff::Pedantic) {
+    // In pedantic mode, we compare index by index (i.e. the strings are in the same order
+    // in both tables.
+    uint32_t Max = std::max(IdList1.size(), IdList2.size());
+    for (uint32_t I = 0; I < Max; ++I) {
+      Optional<uint32_t> Id1, Id2;
+      StringRef S1, S2;
+      if (I < IdList1.size()) {
+        Id1 = IdList1[I];
+        S1 = ST1.getStringForID(*Id1);
+      }
+      if (I < IdList2.size()) {
+        Id2 = IdList2[I];
+        S2 = ST2.getStringForID(*Id2);
+      }
+      if (Id1 == Id2 && S1 == S2)
+        continue;
+
+      std::string OutId1 = Id1 ? formatv("{0}", *Id1).str() : "(index not present)";
+      std::string OutId2 = Id2 ? formatv("{0}", *Id2).str() : "(index not present)";
+      outs() << formatv("  String {0}\n", I);
+      outs() << formatv("    {0}: Hash - {1}, Value - {2}\n", File1.getFilePath(), OutId1, S1);
+      outs() << formatv("    {0}: Hash - {1}, Value - {2}\n", File2.getFilePath(), OutId2, S2);
+      HasDiff = true;
+    }
+  } else {
+    std::vector<StringRef> Strings1, Strings2;
+    Strings1.reserve(IdList1.size());
+    Strings2.reserve(IdList2.size());
+    for (auto ID : IdList1)
+      Strings1.push_back(ST1.getStringForID(ID));
+    for (auto ID : IdList2)
+      Strings2.push_back(ST2.getStringForID(ID));
+
+    SmallVector<StringRef, 64> OnlyP;
+    SmallVector<StringRef, 64> OnlyQ;
+
+    set_differences(Strings1, Strings2, &OnlyP, &OnlyQ, nullptr);
+
+    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 (!HasDiff)
+    outs() << "String Table: No differences detected!\n";
+  return Error::success();
+}
 
 Error DiffStyle::diffFreePageMap() { return Error::success(); }
 




More information about the llvm-commits mailing list