[llvm] r297689 - Add the beginning of PDB diffing support.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 13 16:28:26 PDT 2017
Author: zturner
Date: Mon Mar 13 18:28:25 2017
New Revision: 297689
URL: http://llvm.org/viewvc/llvm-project?rev=297689&view=rev
Log:
Add the beginning of PDB diffing support.
For now this only diffs the stream directory and the MSF
Superblock. Future patches will drill down into individual
streams to find out where the differences lie.
Differential Revision: https://reviews.llvm.org/D30908
Added:
llvm/trunk/tools/llvm-pdbdump/Diff.cpp
llvm/trunk/tools/llvm-pdbdump/Diff.h
llvm/trunk/tools/llvm-pdbdump/StreamUtil.cpp
llvm/trunk/tools/llvm-pdbdump/StreamUtil.h
Modified:
llvm/trunk/tools/llvm-pdbdump/CMakeLists.txt
llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h
llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h
Modified: llvm/trunk/tools/llvm-pdbdump/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/CMakeLists.txt?rev=297689&r1=297688&r2=297689&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-pdbdump/CMakeLists.txt Mon Mar 13 18:28:25 2017
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_tool(llvm-pdbdump
Analyze.cpp
+ Diff.cpp
CompactTypeDumpVisitor.cpp
llvm-pdbdump.cpp
YamlSymbolDumper.cpp
@@ -24,6 +25,7 @@ add_llvm_tool(llvm-pdbdump
PrettyTypeDumper.cpp
PrettyTypedefDumper.cpp
PrettyVariableDumper.cpp
+ StreamUtil.cpp
YAMLOutputStyle.cpp
)
Added: llvm/trunk/tools/llvm-pdbdump/Diff.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/Diff.cpp?rev=297689&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/Diff.cpp (added)
+++ llvm/trunk/tools/llvm-pdbdump/Diff.cpp Mon Mar 13 18:28:25 2017
@@ -0,0 +1,261 @@
+//===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Diff.h"
+
+#include "StreamUtil.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2)
+ : File1(File1), File2(File2) {}
+
+Error DiffStyle::dump() {
+ if (auto EC = diffSuperBlock())
+ return EC;
+
+ if (auto EC = diffFreePageMap())
+ return EC;
+
+ if (auto EC = diffStreamDirectory())
+ return EC;
+
+ if (auto EC = diffStringTable())
+ return EC;
+
+ if (auto EC = diffInfoStream())
+ return EC;
+
+ if (auto EC = diffDbiStream())
+ return EC;
+
+ if (auto EC = diffSectionContribs())
+ return EC;
+
+ if (auto EC = diffSectionMap())
+ return EC;
+
+ if (auto EC = diffFpoStream())
+ return EC;
+
+ if (auto EC = diffTpiStream(StreamTPI))
+ return EC;
+
+ if (auto EC = diffTpiStream(StreamIPI))
+ return EC;
+
+ if (auto EC = diffPublics())
+ return EC;
+
+ if (auto EC = diffGlobals())
+ return EC;
+
+ return Error::success();
+}
+
+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);
+ }
+ return (V1 != V2);
+}
+
+Error DiffStyle::diffSuperBlock() {
+ outs() << "MSF Super Block: Searching for differences...\n";
+ bool Diffs = false;
+
+ Diffs |= diffAndPrint("Block Size", File1, File2, File1.getBlockSize(),
+ File2.getBlockSize());
+ Diffs |= diffAndPrint("Block Count", File1, File2, File1.getBlockCount(),
+ File2.getBlockCount());
+ Diffs |= diffAndPrint("Unknown 1", File1, File2, File1.getUnknown1(),
+ File2.getUnknown1());
+
+ if (opts::diff::Pedantic) {
+ Diffs |= diffAndPrint("Free Block Map", File1, File2,
+ File1.getFreeBlockMapBlock(),
+ File2.getFreeBlockMapBlock());
+ Diffs |= diffAndPrint("Directory Size", File1, File2,
+ File1.getNumDirectoryBytes(),
+ File2.getNumDirectoryBytes());
+ Diffs |= diffAndPrint("Block Map Addr", File1, File2,
+ File1.getBlockMapOffset(), File2.getBlockMapOffset());
+ }
+ if (!Diffs)
+ outs() << "MSF Super Block: No differences detected...\n";
+ return Error::success();
+}
+
+Error DiffStyle::diffStreamDirectory() {
+ SmallVector<std::string, 32> P;
+ SmallVector<std::string, 32> Q;
+ discoverStreamPurposes(File1, P);
+ discoverStreamPurposes(File2, Q);
+ outs() << "Stream Directory: Searching for differences...\n";
+
+ bool HasDifferences = false;
+ if (opts::diff::Pedantic) {
+ size_t Min = std::min(P.size(), Q.size());
+ for (size_t I = 0; I < Min; ++I) {
+ StringRef Names[] = {P[I], Q[I]};
+ uint32_t Sizes[] = {File1.getStreamByteSize(I),
+ File2.getStreamByteSize(I)};
+ bool NamesDiffer = Names[0] != Names[1];
+ bool SizesDiffer = Sizes[0] != Sizes[1];
+ if (NamesDiffer) {
+ HasDifferences = true;
+ outs().indent(2) << formatv("Stream {0} - {1}: {2}, {3}: {4}\n", I,
+ File1.getFilePath(), Names[0],
+ File2.getFilePath(), Names[1]);
+ continue;
+ }
+ if (SizesDiffer) {
+ HasDifferences = true;
+ outs().indent(2) << formatv(
+ "Stream {0} ({1}): {2}: {3} bytes, {4}: {5} bytes\n", I, Names[0],
+ File1.getFilePath(), Sizes[0], File2.getFilePath(), Sizes[1]);
+ continue;
+ }
+ }
+
+ ArrayRef<std::string> MaxNames = (P.size() > Q.size() ? P : Q);
+ size_t Max = std::max(P.size(), Q.size());
+ PDBFile &MaxFile = (P.size() > Q.size() ? File1 : File2);
+ StringRef MinFileName =
+ (P.size() < Q.size() ? File1.getFilePath() : File2.getFilePath());
+ for (size_t I = Min; I < Max; ++I) {
+ HasDifferences = true;
+ StringRef StreamName = MaxNames[I];
+
+ outs().indent(2) << formatv(
+ "Stream {0} - {1}: <not present>, {2}: Index {3}, {4} bytes\n",
+ StreamName, MinFileName, MaxFile.getFilePath(), I,
+ MaxFile.getStreamByteSize(I));
+ }
+ if (!HasDifferences)
+ outs() << "Stream Directory: No differences detected...\n";
+ } else {
+ auto PI = to_vector<32>(enumerate(P));
+ auto QI = to_vector<32>(enumerate(Q));
+
+ typedef decltype(PI) ContainerType;
+ typedef typename ContainerType::value_type value_type;
+
+ 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));
+
+ if (!OnlyP.empty()) {
+ HasDifferences = true;
+ outs().indent(2) << formatv("{0} Stream(s) only in ({1})\n", OnlyP.size(),
+ File1.getFilePath());
+ for (auto &Item : OnlyP) {
+ outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
+ Item.value());
+ }
+ }
+
+ if (!OnlyQ.empty()) {
+ HasDifferences = true;
+ outs().indent(2) << formatv("{0} Streams(s) only in ({1})\n",
+ OnlyQ.size(), File2.getFilePath());
+ for (auto &Item : OnlyQ) {
+ outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
+ Item.value());
+ }
+ }
+ if (!Common.empty()) {
+ outs().indent(2) << formatv("Found {0} common streams. Searching for "
+ "intra-stream differences.\n",
+ Common.size());
+ bool HasCommonDifferences = false;
+ for (const auto &Left : Common) {
+ // Left was copied from the first range so its index refers to a stream
+ // index in the first file. Find the corresponding stream index in the
+ // second file.
+ auto Range =
+ std::equal_range(QI.begin(), QI.end(), Left,
+ [](const value_type &L, const value_type &R) {
+ return L.value() < R.value();
+ });
+ const auto &Right = *Range.first;
+ assert(Left.value() == Right.value());
+ uint32_t LeftSize = File1.getStreamByteSize(Left.index());
+ uint32_t RightSize = File2.getStreamByteSize(Right.index());
+ if (LeftSize != RightSize) {
+ HasDifferences = true;
+ HasCommonDifferences = true;
+ outs().indent(4) << formatv("{0} ({1}: {2} bytes, {3}: {4} bytes)\n",
+ Left.value(), File1.getFilePath(),
+ LeftSize, File2.getFilePath(), RightSize);
+ }
+ }
+ if (!HasCommonDifferences)
+ outs().indent(2) << "Common Streams: No differences detected!\n";
+ }
+ if (!HasDifferences)
+ outs() << "Stream Directory: No differences detected!\n";
+ }
+
+ return Error::success();
+}
+
+Error DiffStyle::diffStringTable() { return Error::success(); }
+
+Error DiffStyle::diffFreePageMap() { return Error::success(); }
+
+Error DiffStyle::diffInfoStream() { return Error::success(); }
+
+Error DiffStyle::diffDbiStream() { return Error::success(); }
+
+Error DiffStyle::diffSectionContribs() { return Error::success(); }
+
+Error DiffStyle::diffSectionMap() { return Error::success(); }
+
+Error DiffStyle::diffFpoStream() { return Error::success(); }
+
+Error DiffStyle::diffTpiStream(int Index) { return Error::success(); }
+
+Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); }
+
+Error DiffStyle::diffPublics() { return Error::success(); }
+
+Error DiffStyle::diffGlobals() { return Error::success(); }
Added: llvm/trunk/tools/llvm-pdbdump/Diff.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/Diff.h?rev=297689&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/Diff.h (added)
+++ llvm/trunk/tools/llvm-pdbdump/Diff.h Mon Mar 13 18:28:25 2017
@@ -0,0 +1,45 @@
+//===- Diff.h - PDB diff utility --------------------------------*- 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_DIFF_H
+#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
+
+#include "OutputStyle.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+class DiffStyle : public OutputStyle {
+public:
+ explicit DiffStyle(PDBFile &File1, PDBFile &File2);
+
+ Error dump() override;
+
+private:
+ Error diffSuperBlock();
+ Error diffStreamDirectory();
+ Error diffStringTable();
+ Error diffFreePageMap();
+ Error diffInfoStream();
+ Error diffDbiStream();
+ Error diffSectionContribs();
+ Error diffSectionMap();
+ Error diffFpoStream();
+ Error diffTpiStream(int Index);
+ Error diffModuleInfoStream(int Index);
+ Error diffPublics();
+ Error diffGlobals();
+
+ PDBFile &File1;
+ PDBFile &File2;
+};
+}
+}
+
+#endif
Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=297689&r1=297688&r2=297689&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Mon Mar 13 18:28:25 2017
@@ -10,6 +10,7 @@
#include "LLVMOutputStyle.h"
#include "CompactTypeDumpVisitor.h"
+#include "StreamUtil.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
@@ -172,124 +173,12 @@ Error LLVMOutputStyle::dumpFileHeaders()
return Error::success();
}
-void LLVMOutputStyle::discoverStreamPurposes() {
- if (!StreamPurposes.empty())
- return;
-
- // It's OK if we fail to load some of these streams, we still attempt to print
- // what we can.
- auto Dbi = File.getPDBDbiStream();
- auto Tpi = File.getPDBTpiStream();
- auto Ipi = File.getPDBIpiStream();
- auto Info = File.getPDBInfoStream();
-
- uint32_t StreamCount = File.getNumStreams();
- std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
- std::unordered_map<uint16_t, std::string> NamedStreams;
-
- if (Dbi) {
- for (auto &ModI : Dbi->modules()) {
- uint16_t SN = ModI.Info.getModuleStreamIndex();
- ModStreams[SN] = &ModI;
- }
- }
- if (Info) {
- for (auto &NSE : Info->named_streams()) {
- NamedStreams[NSE.second] = NSE.first();
- }
- }
-
- StreamPurposes.resize(StreamCount);
- for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- std::string Value;
- if (StreamIdx == OldMSFDirectory)
- Value = "Old MSF Directory";
- else if (StreamIdx == StreamPDB)
- Value = "PDB Stream";
- else if (StreamIdx == StreamDBI)
- Value = "DBI Stream";
- else if (StreamIdx == StreamTPI)
- Value = "TPI Stream";
- else if (StreamIdx == StreamIPI)
- Value = "IPI Stream";
- else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
- Value = "Global Symbol Hash";
- else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
- Value = "Public Symbol Hash";
- else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
- Value = "Public Symbol Records";
- else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
- Value = "TPI Hash";
- else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
- Value = "TPI Aux Hash";
- else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
- Value = "IPI Hash";
- else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
- Value = "IPI Aux Hash";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
- Value = "Exception Data";
- else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
- Value = "Fixup Data";
- else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
- Value = "FPO Data";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
- Value = "New FPO Data";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
- Value = "Omap From Source Data";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
- Value = "Omap To Source Data";
- else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
- Value = "Pdata";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
- Value = "Section Header Data";
- else if (Dbi &&
- StreamIdx ==
- Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
- Value = "Section Header Original Data";
- else if (Dbi &&
- StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
- Value = "Token Rid Data";
- else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
- Value = "Xdata";
- else {
- auto ModIter = ModStreams.find(StreamIdx);
- auto NSIter = NamedStreams.find(StreamIdx);
- if (ModIter != ModStreams.end()) {
- Value = "Module \"";
- Value += ModIter->second->Info.getModuleName().str();
- Value += "\"";
- } else if (NSIter != NamedStreams.end()) {
- Value = "Named Stream \"";
- Value += NSIter->second;
- Value += "\"";
- } else {
- Value = "???";
- }
- }
- StreamPurposes[StreamIdx] = Value;
- }
-
- // Consume errors from missing streams.
- if (!Dbi)
- consumeError(Dbi.takeError());
- if (!Tpi)
- consumeError(Tpi.takeError());
- if (!Ipi)
- consumeError(Ipi.takeError());
- if (!Info)
- consumeError(Info.takeError());
-}
-
Error LLVMOutputStyle::dumpStreamSummary() {
if (!opts::raw::DumpStreamSummary)
return Error::success();
- discoverStreamPurposes();
+ if (StreamPurposes.empty())
+ discoverStreamPurposes(File, StreamPurposes);
uint32_t StreamCount = File.getNumStreams();
@@ -431,7 +320,8 @@ Error LLVMOutputStyle::dumpStreamBytes()
if (opts::raw::DumpStreamData.empty())
return Error::success();
- discoverStreamPurposes();
+ if (StreamPurposes.empty())
+ discoverStreamPurposes(File, StreamPurposes);
DictScope D(P, "Stream Data");
for (uint32_t SI : opts::raw::DumpStreamData) {
Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h?rev=297689&r1=297688&r2=297689&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h Mon Mar 13 18:28:25 2017
@@ -12,9 +12,12 @@
#include "OutputStyle.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/Support/ScopedPrinter.h"
+#include <string>
+
namespace llvm {
class BitVector;
namespace pdb {
@@ -25,8 +28,6 @@ public:
Error dump() override;
private:
- void discoverStreamPurposes();
-
Error dumpFileHeaders();
Error dumpStreamSummary();
Error dumpFreePageMap();
@@ -51,7 +52,7 @@ private:
PDBFile &File;
ScopedPrinter P;
codeview::TypeDatabase TypeDB;
- std::vector<std::string> StreamPurposes;
+ SmallVector<std::string, 32> StreamPurposes;
};
}
}
Added: llvm/trunk/tools/llvm-pdbdump/StreamUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/StreamUtil.cpp?rev=297689&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/StreamUtil.cpp (added)
+++ llvm/trunk/tools/llvm-pdbdump/StreamUtil.cpp Mon Mar 13 18:28:25 2017
@@ -0,0 +1,136 @@
+//===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StreamUtil.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+namespace llvm {
+namespace pdb {
+void discoverStreamPurposes(PDBFile &File,
+ SmallVectorImpl<std::string> &Purposes) {
+
+ // It's OK if we fail to load some of these streams, we still attempt to print
+ // what we can.
+ auto Dbi = File.getPDBDbiStream();
+ auto Tpi = File.getPDBTpiStream();
+ auto Ipi = File.getPDBIpiStream();
+ auto Info = File.getPDBInfoStream();
+
+ uint32_t StreamCount = File.getNumStreams();
+ DenseMap<uint16_t, const ModuleInfoEx *> ModStreams;
+ DenseMap<uint16_t, std::string> NamedStreams;
+
+ if (Dbi) {
+ for (auto &ModI : Dbi->modules()) {
+ uint16_t SN = ModI.Info.getModuleStreamIndex();
+ if (SN != kInvalidStreamIndex)
+ ModStreams[SN] = &ModI;
+ }
+ }
+ if (Info) {
+ for (auto &NSE : Info->named_streams()) {
+ if (NSE.second != kInvalidStreamIndex)
+ NamedStreams[NSE.second] = NSE.first();
+ }
+ }
+
+ Purposes.resize(StreamCount);
+ for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ std::string Value;
+ if (StreamIdx == OldMSFDirectory)
+ Value = "Old MSF Directory";
+ else if (StreamIdx == StreamPDB)
+ Value = "PDB Stream";
+ else if (StreamIdx == StreamDBI)
+ Value = "DBI Stream";
+ else if (StreamIdx == StreamTPI)
+ Value = "TPI Stream";
+ else if (StreamIdx == StreamIPI)
+ Value = "IPI Stream";
+ else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
+ Value = "Global Symbol Hash";
+ else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
+ Value = "Public Symbol Hash";
+ else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
+ Value = "Public Symbol Records";
+ else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
+ Value = "TPI Hash";
+ else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
+ Value = "TPI Aux Hash";
+ else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
+ Value = "IPI Hash";
+ else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
+ Value = "IPI Aux Hash";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
+ Value = "Exception Data";
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
+ Value = "Fixup Data";
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
+ Value = "FPO Data";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
+ Value = "New FPO Data";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
+ Value = "Omap From Source Data";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
+ Value = "Omap To Source Data";
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
+ Value = "Pdata";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
+ Value = "Section Header Data";
+ else if (Dbi &&
+ StreamIdx ==
+ Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
+ Value = "Section Header Original Data";
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
+ Value = "Token Rid Data";
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
+ Value = "Xdata";
+ else {
+ auto ModIter = ModStreams.find(StreamIdx);
+ auto NSIter = NamedStreams.find(StreamIdx);
+ if (ModIter != ModStreams.end()) {
+ Value = "Module \"";
+ Value += ModIter->second->Info.getModuleName().str();
+ Value += "\"";
+ } else if (NSIter != NamedStreams.end()) {
+ Value = "Named Stream \"";
+ Value += NSIter->second;
+ Value += "\"";
+ } else {
+ Value = "???";
+ }
+ }
+ Purposes[StreamIdx] = Value;
+ }
+
+ // Consume errors from missing streams.
+ if (!Dbi)
+ consumeError(Dbi.takeError());
+ if (!Tpi)
+ consumeError(Tpi.takeError());
+ if (!Ipi)
+ consumeError(Ipi.takeError());
+ if (!Info)
+ consumeError(Info.takeError());
+}
+}
+}
Added: llvm/trunk/tools/llvm-pdbdump/StreamUtil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/StreamUtil.h?rev=297689&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/StreamUtil.h (added)
+++ llvm/trunk/tools/llvm-pdbdump/StreamUtil.h Mon Mar 13 18:28:25 2017
@@ -0,0 +1,25 @@
+//===- Streamutil.h - PDB stream utilities ----------------------*- 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_STREAMUTIL_H
+#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <string>
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+void discoverStreamPurposes(PDBFile &File,
+ SmallVectorImpl<std::string> &Purposes);
+}
+}
+
+#endif
Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=297689&r1=297688&r2=297689&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Mon Mar 13 18:28:25 2017
@@ -7,15 +7,14 @@
//
//===----------------------------------------------------------------------===//
//
-// Dumps debug information present in PDB files. This utility makes use of
-// the Microsoft Windows SDK, so will not compile or run on non-Windows
-// platforms.
+// Dumps debug information present in PDB files.
//
//===----------------------------------------------------------------------===//
#include "llvm-pdbdump.h"
#include "Analyze.h"
+#include "Diff.h"
#include "LLVMOutputStyle.h"
#include "LinePrinter.h"
#include "OutputStyle.h"
@@ -81,6 +80,9 @@ cl::SubCommand RawSubcommand("raw", "Dum
cl::SubCommand
PrettySubcommand("pretty",
"Dump semantic information about types and symbols");
+
+cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files");
+
cl::SubCommand
YamlToPdbSubcommand("yaml2pdb",
"Generate a PDB file from a YAML description");
@@ -160,6 +162,17 @@ cl::opt<bool> NoEnumDefs("no-enum-defini
cl::cat(FilterCategory), cl::sub(PrettySubcommand));
}
+namespace diff {
+cl::opt<bool> Pedantic("pedantic",
+ cl::desc("Finds all differences (even structural ones "
+ "that produce otherwise identical PDBs)"),
+ cl::sub(DiffSubcommand));
+
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<first> <second>"),
+ cl::OneOrMore, cl::sub(DiffSubcommand));
+}
+
namespace raw {
cl::OptionCategory MsfOptions("MSF Container Options");
@@ -414,12 +427,17 @@ static void yamlToPdb(StringRef Path) {
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
}
+static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
+ ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
+
+ NativeSession *NS = static_cast<NativeSession *>(Session.get());
+ return NS->getPDBFile();
+}
+
static void pdb2Yaml(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
+ auto &File = loadPDB(Path, Session);
- NativeSession *RS = static_cast<NativeSession *>(Session.get());
- PDBFile &File = RS->getPDBFile();
auto O = llvm::make_unique<YAMLOutputStyle>(File);
O = llvm::make_unique<YAMLOutputStyle>(File);
@@ -428,10 +446,8 @@ static void pdb2Yaml(StringRef Path) {
static void dumpRaw(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
+ auto &File = loadPDB(Path, Session);
- NativeSession *RS = static_cast<NativeSession *>(Session.get());
- PDBFile &File = RS->getPDBFile();
auto O = llvm::make_unique<LLVMOutputStyle>(File);
ExitOnErr(O->dump());
@@ -439,15 +455,24 @@ static void dumpRaw(StringRef Path) {
static void dumpAnalysis(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
-
- NativeSession *NS = static_cast<NativeSession *>(Session.get());
- PDBFile &File = NS->getPDBFile();
+ auto &File = loadPDB(Path, Session);
auto O = llvm::make_unique<AnalysisStyle>(File);
ExitOnErr(O->dump());
}
+static void diff(StringRef Path1, StringRef Path2) {
+ std::unique_ptr<IPDBSession> Session1;
+ std::unique_ptr<IPDBSession> Session2;
+
+ auto &File1 = loadPDB(Path1, Session1);
+ auto &File2 = loadPDB(Path2, Session2);
+
+ auto O = llvm::make_unique<DiffStyle>(File1, File2);
+
+ ExitOnErr(O->dump());
+}
+
static void dumpPretty(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
@@ -669,6 +694,12 @@ int main(int argc_, const char *argv_[])
} else if (opts::RawSubcommand) {
std::for_each(opts::raw::InputFilenames.begin(),
opts::raw::InputFilenames.end(), dumpRaw);
+ } else if (opts::DiffSubcommand) {
+ if (opts::diff::InputFilenames.size() != 2) {
+ errs() << "diff subcommand expects exactly 2 arguments.\n";
+ exit(1);
+ }
+ diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]);
}
outs().flush();
Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h?rev=297689&r1=297688&r2=297689&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h Mon Mar 13 18:28:25 2017
@@ -67,6 +67,10 @@ extern llvm::cl::opt<bool> DumpFpo;
extern llvm::cl::opt<bool> DumpStringTable;
}
+namespace diff {
+extern llvm::cl::opt<bool> Pedantic;
+}
+
namespace pdb2yaml {
extern llvm::cl::opt<bool> NoFileHeaders;
extern llvm::cl::opt<bool> StreamMetadata;
More information about the llvm-commits
mailing list