]> granicus.if.org Git - llvm/commitdiff
[PDB] Add support for parsing Flags from PDB Stream.
authorZachary Turner <zturner@google.com>
Thu, 16 Mar 2017 20:19:11 +0000 (20:19 +0000)
committerZachary Turner <zturner@google.com>
Thu, 16 Mar 2017 20:19:11 +0000 (20:19 +0000)
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.

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

14 files changed:
include/llvm/DebugInfo/PDB/Native/InfoStream.h
include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
include/llvm/DebugInfo/PDB/Native/RawConstants.h
lib/DebugInfo/PDB/Native/InfoStream.cpp
lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
test/DebugInfo/PDB/pdbdump-headers.test
test/DebugInfo/PDB/pdbdump-readwrite.test
test/DebugInfo/PDB/pdbdump-yaml.test
tools/llvm-pdbdump/Diff.cpp
tools/llvm-pdbdump/LLVMOutputStyle.cpp
tools/llvm-pdbdump/PdbYaml.cpp
tools/llvm-pdbdump/PdbYaml.h
tools/llvm-pdbdump/YAMLOutputStyle.cpp
tools/llvm-pdbdump/llvm-pdbdump.cpp

index 4a4222a680e611dccd52f57d49ef9ae6166852a9..1c38c2b6194fc1f7ae81677ed0cb95e6b6cce422 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
 #define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
@@ -40,6 +41,9 @@ public:
   PDB_UniqueId getGuid() const;
   uint32_t getNamedStreamMapByteSize() const;
 
+  PdbRaw_Features getFeatures() const;
+  ArrayRef<PdbRaw_FeatureSig> getFeatureSignatures() const;
+
   const NamedStreamMap &getNamedStreams() const;
 
   uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
@@ -66,6 +70,9 @@ private:
   // universally unique.
   PDB_UniqueId Guid;
 
+  std::vector<PdbRaw_FeatureSig> FeatureSignatures;
+  PdbRaw_Features Features = PdbFeatureNone;
+
   uint32_t NamedStreamMapByteSize = 0;
 
   NamedStreamMap NamedStreams;
index 4133662615be8621e07cd72207b0c16b9ed07c5a..90c28a90d25233c80f2b37132c127694a8f681ae 100644 (file)
@@ -38,6 +38,7 @@ public:
   void setSignature(uint32_t S);
   void setAge(uint32_t A);
   void setGuid(PDB_UniqueId G);
+  void addFeature(PdbRaw_FeatureSig Sig);
 
   uint32_t finalize();
 
@@ -49,6 +50,7 @@ public:
 private:
   msf::MSFBuilder &Msf;
 
+  std::vector<PdbRaw_FeatureSig> Features;
   PdbRaw_ImplVer Ver;
   uint32_t Sig;
   uint32_t Age;
index af114ff524916c8e1b801282ce5ef5cae31dc25c..f5d4df8feb2ed2307771b4e2c46380a64267ee75 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
 #define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 
 #include <cstdint>
@@ -32,6 +33,21 @@ enum PdbRaw_ImplVer : uint32_t {
   PdbImplVC140 = 20140508,
 };
 
+enum class PdbRaw_FeatureSig : uint32_t {
+  VC110 = PdbImplVC110,
+  VC140 = PdbImplVC140,
+  NoTypeMerge = 0x4D544F4E,
+  MinimalDebugInfo = 0x494E494D,
+};
+
+enum PdbRaw_Features : uint32_t {
+  PdbFeatureNone = 0x0,
+  PdbFeatureContainsIdStream = 0x1,
+  PdbFeatureMinimalDebugInfo = 0x2,
+  PdbFeatureNoTypeMerging = 0x4,
+  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PdbFeatureNoTypeMerging)
+};
+
 enum PdbRaw_DbiVer : uint32_t {
   PdbDbiVC41 = 930803,
   PdbDbiV50 = 19960307,
index 1ce0fe842065a024c5fa526d09145ff607d0b03a..0b223379b264b2181ecfa0c2883ed79164061b46 100644 (file)
@@ -56,6 +56,30 @@ Error InfoStream::reload() {
     return EC;
   uint32_t NewOffset = Reader.getOffset();
   NamedStreamMapByteSize = NewOffset - Offset;
+
+  bool Stop = false;
+  while (!Stop && !Reader.empty()) {
+    PdbRaw_FeatureSig Sig;
+    if (auto EC = Reader.readEnum(Sig))
+      return EC;
+    switch (Sig) {
+    case PdbRaw_FeatureSig::VC110:
+      // No other flags for VC110 PDB.
+      Stop = true;
+      LLVM_FALLTHROUGH;
+    case PdbRaw_FeatureSig::VC140:
+      Features |= PdbFeatureContainsIdStream;
+      break;
+    case PdbRaw_FeatureSig::NoTypeMerge:
+      Features |= PdbFeatureNoTypeMerging;
+      break;
+    case PdbRaw_FeatureSig::MinimalDebugInfo:
+      Features |= PdbFeatureMinimalDebugInfo;
+    default:
+      continue;
+    }
+    FeatureSignatures.push_back(Sig);
+  }
   return Error::success();
 }
 
@@ -87,6 +111,12 @@ uint32_t InfoStream::getNamedStreamMapByteSize() const {
   return NamedStreamMapByteSize;
 }
 
+PdbRaw_Features InfoStream::getFeatures() const { return Features; }
+
+ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {
+  return FeatureSignatures;
+}
+
 const NamedStreamMap &InfoStream::getNamedStreams() const {
   return NamedStreams;
 }
index f5b50a127db0d28065a5ed838d0d09235297f967..f019d410328a84357d30f0876da42efbf8f19012 100644 (file)
@@ -36,8 +36,13 @@ void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
 
 void InfoStreamBuilder::setGuid(PDB_UniqueId G) { Guid = G; }
 
+void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
+  Features.push_back(Sig);
+}
+
 Error InfoStreamBuilder::finalizeMsfLayout() {
-  uint32_t Length = sizeof(InfoStreamHeader) + NamedStreams.finalize();
+  uint32_t Length = sizeof(InfoStreamHeader) + NamedStreams.finalize() +
+                    (Features.size() + 1) * sizeof(uint32_t);
   if (auto EC = Msf.setStreamSize(StreamPDB, Length))
     return EC;
   return Error::success();
@@ -57,5 +62,13 @@ Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
   if (auto EC = Writer.writeObject(H))
     return EC;
 
-  return NamedStreams.commit(Writer);
+  if (auto EC = NamedStreams.commit(Writer))
+    return EC;
+  if (auto EC = Writer.writeInteger(0))
+    return EC;
+  for (auto E : Features) {
+    if (auto EC = Writer.writeEnum(E))
+      return EC;
+  }
+  return Error::success();
 }
index 5fb3ad9220a0d14e31c53f61e792eaec2785d00e..c10d866f4a831cae23a535c464f62c9b96a7a3db 100644 (file)
@@ -71,6 +71,7 @@
 ; EMPTY-NEXT:   Signature: 0x54E507E2
 ; EMPTY-NEXT:   Age: 1
 ; EMPTY-NEXT:   Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
+; EMPTY-NEXT:   Features: 0x1
 ; EMPTY-NEXT:   Named Streams {
 ; EMPTY-NEXT:     /names: 13
 ; EMPTY-NEXT:     /LinkInfo: 5
 ; ALL:   Signature: 0x54E507E2
 ; ALL:   Age: 1
 ; ALL:   Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
+; ALL:   Features: 0x1
 ; ALL: }
 ; ALL: Type Info Stream (IPI) {
 ; ALL:   IPI Version: 20040203
 ; BIG-NEXT:   Signature: 0x571FFE67
 ; BIG-NEXT:   Age: 1
 ; BIG-NEXT:   Guid: {880ECC89-DF81-0B4F-839C-58CBD052E937}
+; BIG-NEXT:   Features: 0x1
 ; BIG-NEXT:   Named Streams {
 ; BIG-NEXT:     /names: 13
 ; BIG-NEXT:     /LinkInfo: 5
index 780612aa65d76b41d7019ec41d9998d8d013cad0..4756faf68c2d625715aa957b9b57317337bec7c8 100644 (file)
@@ -27,6 +27,7 @@ CHECK-NEXT:   Version: 20000404
 CHECK-NEXT:   Signature: 0x54E507E2
 CHECK-NEXT:   Age: 1
 CHECK-NEXT:   Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
+CHECK-NEXT:   Features: 0x1
 CHECK-NEXT:   Named Streams {
 CHECK:          /names: 
 CHECK:        }
index e4cb5f5608be2970d6c272789252065dbba2848a..44025be5bca73378a986576d8d2bf993945fa563 100644 (file)
@@ -44,6 +44,7 @@
 ; YAML-NEXT:   Age:             1
 ; YAML-NEXT:   Guid:            '{0B355641-86A0-A249-896F-9988FAE52FF0}'
 ; YAML-NEXT:   Signature:       1424295906
+; YAML-NEXT:   Features:        [ VC110 ]
 ; YAML-NEXT:   Version:         VC70
 ; YAML-NEXT: ...
 
index 529e57da5c1f149913e60ad6a262d7066dc46a36..8c02d36044d82b038e7a33ac1248b83ba911ac7b 100644 (file)
 #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>
@@ -127,6 +150,22 @@ static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1,
   return true;
 }
 
+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,
@@ -446,6 +485,8 @@ Error DiffStyle::diffInfoStream() {
                           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());
index 04a9c41e47ba7d9039bb3770d007c965825ff673..d94b398e580c211ea17e58317fea6112f924771b 100644 (file)
@@ -387,6 +387,7 @@ Error LLVMOutputStyle::dumpInfoStream() {
   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())
index 21f5a775c55a30d4118f461bba7f50a98c60c304..e2c4ee967ed36e12bbc5a5804dda6e7287fbb032 100644 (file)
@@ -38,6 +38,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
 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 @@ template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> {
     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 @@ void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) {
   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);
 }
 
index 7632d7e0b605a6a8a789b7a7d0670b436d7164d7..2c4cd237f8d7f69187dae24a0741954ee6f9ee35 100644 (file)
@@ -52,6 +52,7 @@ struct PdbInfoStream {
   uint32_t Signature = 0;
   uint32_t Age = 1;
   PDB_UniqueId Guid;
+  std::vector<PdbRaw_FeatureSig> Features;
   std::vector<NamedStreamMapping> NamedStreams;
 };
 
index fab3760fabb23d1a4c5bd8a8ab34fe0d5416eb31..5b53d2137166a02c288e2e0b418c74288b3f947f 100644 (file)
@@ -145,6 +145,7 @@ Error YAMLOutputStyle::dumpPDBStream() {
   Obj.PdbStream->Guid = InfoS.getGuid();
   Obj.PdbStream->Signature = InfoS.getSignature();
   Obj.PdbStream->Version = InfoS.getVersion();
+  Obj.PdbStream->Features = InfoS.getFeatureSignatures();
 
   return Error::success();
 }
index 7dd4eec1fe5b2dfd50b8b208a8be235cf14bd087..8b166411f0bfb15dfb7e53fc0383bd06dcc49ca4 100644 (file)
@@ -404,6 +404,8 @@ static void yamlToPdb(StringRef Path) {
   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 @@ static void yamlToPdb(StringRef Path) {
   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));