--- /dev/null
+//===- 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
#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"
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() {
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(),
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);
-
- 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);
+ printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String");
+
+ 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)
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(); }