[PDB] Add support for parsing Flags from PDB Stream.
This was discovered when running `llvm-pdbdump diff` against
two files, the second of which was generated by running the
first one through pdb2yaml and then yaml2pdb.
The second one was missing some bytes from the PDB Stream, and
tracking this down showed that at the end of the PDB Stream were
some additional bytes that we were ignoring. Looking back
to the reference code, these seem to specify some additional
flags that indicate whether the PDB supports various optional
features.
This patch adds support for reading, writing, and round-tripping
these flags through YAML and the raw dumper, and updates the
tests accordingly.
llvm-svn: 297984
diff --git a/llvm/tools/llvm-pdbdump/Diff.cpp b/llvm/tools/llvm-pdbdump/Diff.cpp
index 529e57d..8c02d36 100644
--- a/llvm/tools/llvm-pdbdump/Diff.cpp
+++ b/llvm/tools/llvm-pdbdump/Diff.cpp
@@ -19,11 +19,34 @@
#include "llvm/DebugInfo/PDB/Native/StringTable.h"
#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::pdb;
+namespace llvm {
+template <> struct format_provider<PdbRaw_FeatureSig> {
+ static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream,
+ StringRef Style) {
+ switch (Sig) {
+ case PdbRaw_FeatureSig::MinimalDebugInfo:
+ Stream << "MinimalDebugInfo";
+ break;
+ case PdbRaw_FeatureSig::NoTypeMerge:
+ Stream << "NoTypeMerge";
+ break;
+ case PdbRaw_FeatureSig::VC110:
+ Stream << "VC110";
+ break;
+ case PdbRaw_FeatureSig::VC140:
+ Stream << "VC140";
+ break;
+ }
+ }
+};
+}
+
template <typename R> using ValueOfRange = llvm::detail::ValueOfRange<R>;
template <typename Range, typename Comp>
@@ -128,6 +151,22 @@
}
template <typename T>
+static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2,
+ ArrayRef<T> V1, ArrayRef<T> V2) {
+ if (V1 == V2) {
+ outs() << formatv(" {0}: No differences detected!\n", Label);
+ return false;
+ }
+
+ outs().indent(2) << Label << "\n";
+ outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(),
+ make_range(V1.begin(), V1.end()));
+ outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(),
+ make_range(V2.begin(), V2.end()));
+ return true;
+}
+
+template <typename T>
static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2,
T &&OnlyRange1, T &&OnlyRange2,
StringRef Label) {
@@ -446,6 +485,8 @@
IS2.getSignature());
HasDiff |=
diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion());
+ HasDiff |= diffAndPrint("Features", File1, File2, IS1.getFeatureSignatures(),
+ IS2.getFeatureSignatures());
HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2,
IS1.getNamedStreamMapByteSize(),
IS2.getNamedStreamMapByteSize());
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
index 04a9c41..d94b398 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -387,6 +387,7 @@
P.printHex("Signature", IS->getSignature());
P.printNumber("Age", IS->getAge());
P.printObject("Guid", IS->getGuid());
+ P.printHex("Features", IS->getFeatures());
{
DictScope DD(P, "Named Streams");
for (const auto &S : IS->getNamedStreams().entries())
diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
index 21f5a77..e2c4ee9 100644
--- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp
+++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
@@ -38,6 +38,7 @@
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSymbolRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig)
namespace llvm {
namespace yaml {
@@ -134,6 +135,16 @@
io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80);
}
};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_FeatureSig> {
+ static void enumeration(IO &io, PdbRaw_FeatureSig &Features) {
+ io.enumCase(Features, "MinimalDebugInfo",
+ PdbRaw_FeatureSig::MinimalDebugInfo);
+ io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge);
+ io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110);
+ io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140);
+ }
+};
}
}
@@ -187,6 +198,7 @@
IO.mapOptional("Age", Obj.Age, 1U);
IO.mapOptional("Guid", Obj.Guid);
IO.mapOptional("Signature", Obj.Signature, 0U);
+ IO.mapOptional("Features", Obj.Features);
IO.mapOptional("Version", Obj.Version, PdbImplVC70);
}
diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.h b/llvm/tools/llvm-pdbdump/PdbYaml.h
index 7632d7e..2c4cd23 100644
--- a/llvm/tools/llvm-pdbdump/PdbYaml.h
+++ b/llvm/tools/llvm-pdbdump/PdbYaml.h
@@ -52,6 +52,7 @@
uint32_t Signature = 0;
uint32_t Age = 1;
PDB_UniqueId Guid;
+ std::vector<PdbRaw_FeatureSig> Features;
std::vector<NamedStreamMapping> NamedStreams;
};
diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
index fab3760..5b53d21 100644
--- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
@@ -145,6 +145,7 @@
Obj.PdbStream->Guid = InfoS.getGuid();
Obj.PdbStream->Signature = InfoS.getSignature();
Obj.PdbStream->Version = InfoS.getVersion();
+ Obj.PdbStream->Features = InfoS.getFeatureSignatures();
return Error::success();
}
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 7dd4eec..8b16641 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -404,6 +404,8 @@
InfoBuilder.setGuid(Info.Guid);
InfoBuilder.setSignature(Info.Signature);
InfoBuilder.setVersion(Info.Version);
+ for (auto F : Info.Features)
+ InfoBuilder.addFeature(F);
const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
auto &DbiBuilder = Builder.getDbiBuilder();
@@ -415,7 +417,7 @@
DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
DbiBuilder.setVersionHeader(Dbi.VerHeader);
for (const auto &MI : Dbi.ModInfos) {
- auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Obj));
+ auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
for (auto S : MI.SourceFiles)
ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S));