From: Zachary Turner Date: Thu, 3 Aug 2017 20:30:09 +0000 (+0000) Subject: [llvm-pdbutil] Allow diff to force module equivalencies. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c593673c880e802e5fef86d3c3063a67937c524c;p=llvm [llvm-pdbutil] Allow diff to force module equivalencies. 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 --- diff --git a/tools/llvm-pdbutil/Diff.cpp b/tools/llvm-pdbutil/Diff.cpp index aad4e1bf142..fb52545df0f 100644 --- a/tools/llvm-pdbutil/Diff.cpp +++ b/tools/llvm-pdbutil/Diff.cpp @@ -425,20 +425,66 @@ Error DiffStyle::diffInfoStream() { return Error::success(); } -static std::vector> +typedef std::pair IndexedModuleDescriptor; +typedef std::vector IndexedModuleDescriptorList; + +static IndexedModuleDescriptorList getModuleDescriptors(const DbiModuleList &ML) { - std::vector> 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 Item, - std::vector> &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 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 &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("- Modi", Item.first, None); + if (ItemIsRight) + D.print("- Modi", None, Item.first); + else + D.print("- Modi", Item.first, None); return; } @@ -472,6 +509,7 @@ diffOneModule(DiffPrinter &D, if (ItemIsRight) std::swap(L, R); + BinaryPathProvider PathProvider(28); D.print("- Modi", L->first, R->first); D.print("- Obj File Name", L->second.getObjFileName(), R->second.getObjFileName(), PathProvider); diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp index 99766870ebe..051977ba5c2 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -293,6 +293,13 @@ cl::opt cl::desc("Print a column with the result status"), cl::Optional, cl::sub(DiffSubcommand)); +cl::list + 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 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 Left(cl::Positional, cl::desc(""), cl::sub(DiffSubcommand)); cl::opt Right(cl::Positional, cl::desc(""), cl::sub(DiffSubcommand)); + +llvm::DenseMap 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) { diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h index e4e9a4a5de1..88bebf95aaa 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -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 DumpModuleSyms; namespace diff { extern llvm::cl::opt PrintValueColumns; extern llvm::cl::opt PrintResultColumn; +extern llvm::DenseMap Equivalences; extern llvm::cl::opt LeftRoot; extern llvm::cl::opt RightRoot; } // namespace diff