OSDN Git Service

[llvm-pdbutil] Allow diff to force module equivalencies.
authorZachary Turner <zturner@google.com>
Thu, 3 Aug 2017 20:30:09 +0000 (20:30 +0000)
committerZachary Turner <zturner@google.com>
Thu, 3 Aug 2017 20:30:09 +0000 (20:30 +0000)
Sometimes the normal module equivalence detection algorithm doesn't
quite work.  For example, you might build the same program with
MSVC and clang-cl, outputting to different object files, exes, and
PDBs, then compare them.  If the object files have different names
though, then they won't be treated as equivalent.  This way we
can force specific module indices to be treated as equivalent.

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

tools/llvm-pdbutil/Diff.cpp
tools/llvm-pdbutil/llvm-pdbutil.cpp
tools/llvm-pdbutil/llvm-pdbutil.h

index aad4e1b..fb52545 100644 (file)
@@ -425,20 +425,66 @@ Error DiffStyle::diffInfoStream() {
   return Error::success();
 }
 
-static std::vector<std::pair<uint32_t, DbiModuleDescriptor>>
+typedef std::pair<uint32_t, DbiModuleDescriptor> IndexedModuleDescriptor;
+typedef std::vector<IndexedModuleDescriptor> IndexedModuleDescriptorList;
+
+static IndexedModuleDescriptorList
 getModuleDescriptors(const DbiModuleList &ML) {
-  std::vector<std::pair<uint32_t, DbiModuleDescriptor>> List;
+  IndexedModuleDescriptorList List;
   List.reserve(ML.getModuleCount());
   for (uint32_t I = 0; I < ML.getModuleCount(); ++I)
     List.emplace_back(I, ML.getModuleDescriptor(I));
   return List;
 }
 
-static void
-diffOneModule(DiffPrinter &D,
-              const std::pair<uint32_t, DbiModuleDescriptor> Item,
-              std::vector<std::pair<uint32_t, DbiModuleDescriptor>> &Other,
-              bool ItemIsRight) {
+static IndexedModuleDescriptorList::iterator
+findOverrideEquivalentModule(uint32_t Modi,
+                             IndexedModuleDescriptorList &OtherList) {
+  auto &EqMap = opts::diff::Equivalences;
+
+  auto Iter = EqMap.find(Modi);
+  if (Iter == EqMap.end())
+    return OtherList.end();
+
+  uint32_t EqValue = Iter->second;
+
+  return llvm::find_if(OtherList,
+                       [EqValue](const IndexedModuleDescriptor &Desc) {
+                         return Desc.first == EqValue;
+                       });
+}
+
+static IndexedModuleDescriptorList::iterator
+findEquivalentModule(const IndexedModuleDescriptor &Item,
+                     IndexedModuleDescriptorList &OtherList, bool ItemIsRight) {
+
+  if (!ItemIsRight) {
+    uint32_t Modi = Item.first;
+    auto OverrideIter = findOverrideEquivalentModule(Modi, OtherList);
+    if (OverrideIter != OtherList.end())
+      return OverrideIter;
+  }
+
+  BinaryPathProvider PathProvider(28);
+
+  auto Iter = OtherList.begin();
+  auto End = OtherList.end();
+  for (; Iter != End; ++Iter) {
+    const IndexedModuleDescriptor *Left = &Item;
+    const IndexedModuleDescriptor *Right = &*Iter;
+    if (ItemIsRight)
+      std::swap(Left, Right);
+    DiffResult Result = PathProvider.compare(Left->second.getModuleName(),
+                                             Right->second.getModuleName());
+    if (Result == DiffResult::EQUIVALENT || Result == DiffResult::IDENTICAL)
+      return Iter;
+  }
+  return OtherList.end();
+}
+
+static void diffOneModule(DiffPrinter &D, const IndexedModuleDescriptor &Item,
+                          IndexedModuleDescriptorList &Other,
+                          bool ItemIsRight) {
   StreamPurposeProvider HeaderProvider(70);
   std::pair<StreamPurpose, std::string> Header;
   Header.first = StreamPurpose::ModuleStream;
@@ -447,23 +493,14 @@ diffOneModule(DiffPrinter &D,
 
   const auto *L = &Item;
 
-  BinaryPathProvider PathProvider(28);
-  auto Iter = llvm::find_if(
-      Other, [&PathProvider, ItemIsRight,
-              L](const std::pair<uint32_t, DbiModuleDescriptor> &Other) {
-        const auto *Left = L;
-        const auto *Right = &Other;
-        if (ItemIsRight)
-          std::swap(Left, Right);
-        DiffResult Result = PathProvider.compare(Left->second.getModuleName(),
-                                                 Right->second.getModuleName());
-        return Result == DiffResult::EQUIVALENT ||
-               Result == DiffResult::IDENTICAL;
-      });
+  auto Iter = findEquivalentModule(Item, Other, ItemIsRight);
   if (Iter == Other.end()) {
     // We didn't find this module at all on the other side.  Just print one row
     // and continue.
-    D.print<ModiProvider>("- Modi", Item.first, None);
+    if (ItemIsRight)
+      D.print<ModiProvider>("- Modi", None, Item.first);
+    else
+      D.print<ModiProvider>("- Modi", Item.first, None);
     return;
   }
 
@@ -472,6 +509,7 @@ diffOneModule(DiffPrinter &D,
   if (ItemIsRight)
     std::swap(L, R);
 
+  BinaryPathProvider PathProvider(28);
   D.print<ModiProvider>("- Modi", L->first, R->first);
   D.print<BinaryPathProvider>("- Obj File Name", L->second.getObjFileName(),
                               R->second.getObjFileName(), PathProvider);
index 9976687..051977b 100644 (file)
@@ -293,6 +293,13 @@ cl::opt<bool>
                       cl::desc("Print a column with the result status"),
                       cl::Optional, cl::sub(DiffSubcommand));
 
+cl::list<std::string>
+    RawModiEquivalences("modi-equivalence", cl::ZeroOrMore,
+                        cl::value_desc("left,right"),
+                        cl::desc("Modules with the specified indices will be "
+                                 "treated as referring to the same module"),
+                        cl::sub(DiffSubcommand));
+
 cl::opt<std::string> LeftRoot(
     "left-bin-root", cl::Optional,
     cl::desc("Treats the specified path as the root of the tree containing "
@@ -310,6 +317,8 @@ cl::opt<std::string> Left(cl::Positional, cl::desc("<left>"),
                           cl::sub(DiffSubcommand));
 cl::opt<std::string> Right(cl::Positional, cl::desc("<right>"),
                            cl::sub(DiffSubcommand));
+
+llvm::DenseMap<uint32_t, uint32_t> Equivalences;
 }
 
 cl::OptionCategory FileOptions("Module & File Options");
@@ -1175,6 +1184,19 @@ int main(int argc_, const char *argv_[]) {
     std::for_each(opts::bytes::InputFilenames.begin(),
                   opts::bytes::InputFilenames.end(), dumpBytes);
   } else if (opts::DiffSubcommand) {
+    for (StringRef S : opts::diff::RawModiEquivalences) {
+      StringRef Left;
+      StringRef Right;
+      std::tie(Left, Right) = S.split(',');
+      uint32_t X, Y;
+      if (!to_integer(Left, X) || !to_integer(Right, Y)) {
+        errs() << formatv("invalid value {0} specified for modi equivalence\n",
+                          S);
+        exit(1);
+      }
+      opts::diff::Equivalences[X] = Y;
+    }
+
     diff(opts::diff::Left, opts::diff::Right);
   } else if (opts::MergeSubcommand) {
     if (opts::merge::InputFilenames.size() < 2) {
index e4e9a4a..88bebf9 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
 #define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/raw_ostream.h"
@@ -177,6 +178,7 @@ extern llvm::cl::opt<bool> DumpModuleSyms;
 namespace diff {
 extern llvm::cl::opt<bool> PrintValueColumns;
 extern llvm::cl::opt<bool> PrintResultColumn;
+extern llvm::DenseMap<uint32_t, uint32_t> Equivalences;
 extern llvm::cl::opt<std::string> LeftRoot;
 extern llvm::cl::opt<std::string> RightRoot;
 } // namespace diff