]> granicus.if.org Git - llvm/commitdiff
[llvm-pdbdump] Add support for dumping symbols from Yaml -> PDB.
authorZachary Turner <zturner@google.com>
Mon, 13 Mar 2017 14:57:45 +0000 (14:57 +0000)
committerZachary Turner <zturner@google.com>
Mon, 13 Mar 2017 14:57:45 +0000 (14:57 +0000)
Previously we could round-trip type records from PDB -> Yaml ->
PDB, but for symbols we could only go from PDB -> Yaml.  This
completes the round-tripping for symbols as well.

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

include/llvm/DebugInfo/CodeView/SymbolSerializer.h
lib/DebugInfo/CodeView/CMakeLists.txt
lib/DebugInfo/CodeView/SymbolSerializer.cpp [new file with mode: 0644]
tools/llvm-pdbdump/PdbYaml.cpp
tools/llvm-pdbdump/PdbYaml.h
tools/llvm-pdbdump/YamlSymbolDumper.cpp

index 894e623f078b26921d437d7b3b6d8990cd05ee97..54fcd092c4e04e6fc83637b23b3ff988bb4d956a 100644 (file)
@@ -29,7 +29,10 @@ namespace codeview {
 
 class SymbolSerializer : public SymbolVisitorCallbacks {
   uint32_t RecordStart = 0;
-  BinaryStreamWriter &Writer;
+  BumpPtrAllocator &Storage;
+  std::vector<uint8_t> RecordBuffer;
+  MutableBinaryByteStream Stream;
+  BinaryStreamWriter Writer;
   SymbolRecordMapping Mapping;
   Optional<SymbolKind> CurrentSymbol;
 
@@ -43,40 +46,10 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
   }
 
 public:
-  explicit SymbolSerializer(BinaryStreamWriter &Writer)
-      : Writer(Writer), Mapping(Writer) {}
+  explicit SymbolSerializer(BumpPtrAllocator &Storage);
 
-  virtual Error visitSymbolBegin(CVSymbol &Record) override {
-    assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!");
-
-    RecordStart = Writer.getOffset();
-    if (auto EC = writeRecordPrefix(Record.kind()))
-      return EC;
-
-    CurrentSymbol = Record.kind();
-    if (auto EC = Mapping.visitSymbolBegin(Record))
-      return EC;
-
-    return Error::success();
-  }
-
-  virtual Error visitSymbolEnd(CVSymbol &Record) override {
-    assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!");
-
-    if (auto EC = Mapping.visitSymbolEnd(Record))
-      return EC;
-
-    uint32_t RecordEnd = Writer.getOffset();
-    Writer.setOffset(RecordStart);
-    uint16_t Length = RecordEnd - Writer.getOffset() - 2;
-    if (auto EC = Writer.writeInteger(Length))
-      return EC;
-
-    Writer.setOffset(RecordEnd);
-    CurrentSymbol.reset();
-
-    return Error::success();
-  }
+  virtual Error visitSymbolBegin(CVSymbol &Record) override;
+  virtual Error visitSymbolEnd(CVSymbol &Record) override;
 
 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
   virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {       \
index 63c1832b3f225d701dd2ed03d56cc991db36c77a..a120484cdbeeb2811ef701fcdb14a2ae1951320d 100644 (file)
@@ -12,6 +12,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   RecordSerialization.cpp
   SymbolRecordMapping.cpp
   SymbolDumper.cpp
+  SymbolSerializer.cpp
   TypeDatabase.cpp
   TypeDatabaseVisitor.cpp
   TypeDumpVisitor.cpp
diff --git a/lib/DebugInfo/CodeView/SymbolSerializer.cpp b/lib/DebugInfo/CodeView/SymbolSerializer.cpp
new file mode 100644 (file)
index 0000000..251cc43
--- /dev/null
@@ -0,0 +1,52 @@
+//===- SymbolSerializer.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+SymbolSerializer::SymbolSerializer(BumpPtrAllocator &Allocator)
+  : Storage(Allocator), RecordBuffer(MaxRecordLength), Stream(RecordBuffer, llvm::support::little),
+  Writer(Stream), Mapping(Writer) { }
+
+Error SymbolSerializer::visitSymbolBegin(CVSymbol &Record) {
+  assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!");
+
+  Writer.setOffset(0);
+
+  if (auto EC = writeRecordPrefix(Record.kind()))
+    return EC;
+
+  CurrentSymbol = Record.kind();
+  if (auto EC = Mapping.visitSymbolBegin(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error SymbolSerializer::visitSymbolEnd(CVSymbol &Record) {
+  assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!");
+
+  if (auto EC = Mapping.visitSymbolEnd(Record))
+    return EC;
+
+  uint32_t RecordEnd = Writer.getOffset();
+  uint16_t Length = RecordEnd - 2;
+  Writer.setOffset(0);
+  if (auto EC = Writer.writeInteger(Length))
+    return EC;
+
+  uint8_t *StableStorage = Storage.Allocate<uint8_t>(RecordEnd);
+  ::memcpy(StableStorage, &RecordBuffer[0], RecordEnd);
+  Record.RecordData = ArrayRef<uint8_t>(StableStorage, RecordEnd);
+  CurrentSymbol.reset();
+
+  return Error::success();
+}
index ba2acf7e7f1238556652d6b2bcc3d4526a8e0d3d..9877af0a07c406f3cc8dfbe6a5ccec820bd32fb4 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
@@ -137,14 +138,23 @@ template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> {
 }
 
 void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
+  // Create a single serialization context that will be passed through the
+  // entire process of serializing / deserializing a Tpi Stream.  This is
+  // especially important when we are going from Pdb -> Yaml because we need
+  // to maintain state in a TypeTableBuilder across mappings, and at the end of
+  // the entire process, we need to have one TypeTableBuilder that has every
+  // record.
+  pdb::yaml::SerializationContext Context(IO, Obj.Allocator);
+
+
   IO.mapOptional("MSF", Obj.Headers);
   IO.mapOptional("StreamSizes", Obj.StreamSizes);
   IO.mapOptional("StreamMap", Obj.StreamMap);
   IO.mapOptional("StringTable", Obj.StringTable);
   IO.mapOptional("PdbStream", Obj.PdbStream);
-  IO.mapOptional("DbiStream", Obj.DbiStream);
-  IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
-  IO.mapOptionalWithContext("IpiStream", Obj.IpiStream, Obj.Allocator);
+  IO.mapOptionalWithContext("DbiStream", Obj.DbiStream, Context);
+  IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Context);
+  IO.mapOptionalWithContext("IpiStream", Obj.IpiStream, Context);
 }
 
 void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
@@ -179,7 +189,7 @@ void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) {
   IO.mapRequired("Version", Obj.Version);
 }
 
-void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
+void MappingContextTraits<PdbDbiStream, pdb::yaml::SerializationContext>::mapping(IO &IO, PdbDbiStream &Obj, pdb::yaml::SerializationContext &Context) {
   IO.mapRequired("VerHeader", Obj.VerHeader);
   IO.mapRequired("Age", Obj.Age);
   IO.mapRequired("BuildNumber", Obj.BuildNumber);
@@ -187,19 +197,11 @@ void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
   IO.mapRequired("PdbDllRbld", Obj.PdbDllRbld);
   IO.mapRequired("Flags", Obj.Flags);
   IO.mapRequired("MachineType", Obj.MachineType);
-  IO.mapOptional("Modules", Obj.ModInfos);
+  IO.mapOptionalWithContext("Modules", Obj.ModInfos, Context);
 }
 
-void MappingContextTraits<PdbTpiStream, BumpPtrAllocator>::mapping(
-    IO &IO, pdb::yaml::PdbTpiStream &Obj, BumpPtrAllocator &Allocator) {
-  // Create a single serialization context that will be passed through the
-  // entire process of serializing / deserializing a Tpi Stream.  This is
-  // especially important when we are going from Pdb -> Yaml because we need
-  // to maintain state in a TypeTableBuilder across mappings, and at the end of
-  // the entire process, we need to have one TypeTableBuilder that has every
-  // record.
-  pdb::yaml::SerializationContext Context(IO, Allocator);
-
+void MappingContextTraits<PdbTpiStream, pdb::yaml::SerializationContext>::mapping(
+    IO &IO, pdb::yaml::PdbTpiStream &Obj, pdb::yaml::SerializationContext &Context) {
   IO.mapRequired("Version", Obj.Version);
   IO.mapRequired("Records", Obj.Records, Context);
 }
@@ -210,8 +212,9 @@ void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
   IO.mapRequired("StreamNum", Obj.StreamNumber);
 }
 
-void MappingTraits<PdbSymbolRecord>::mapping(IO &IO, PdbSymbolRecord &Obj) {
+void MappingContextTraits<PdbSymbolRecord, pdb::yaml::SerializationContext>::mapping(IO &IO, PdbSymbolRecord &Obj, pdb::yaml::SerializationContext &Context) {
   codeview::SymbolVisitorCallbackPipeline Pipeline;
+  codeview::SymbolSerializer Serializer(Context.Allocator);
   codeview::SymbolDeserializer Deserializer(nullptr);
   codeview::yaml::YamlSymbolDumper Dumper(IO);
 
@@ -220,23 +223,26 @@ void MappingTraits<PdbSymbolRecord>::mapping(IO &IO, PdbSymbolRecord &Obj) {
     Pipeline.addCallbackToPipeline(Deserializer);
     Pipeline.addCallbackToPipeline(Dumper);
   } else {
-    return;
+    // For the other way around, dump it into a concrete structure, and then
+    // serialize it into the CVRecord.
+    Pipeline.addCallbackToPipeline(Dumper);
+    Pipeline.addCallbackToPipeline(Serializer);
   }
 
   codeview::CVSymbolVisitor Visitor(Pipeline);
   consumeError(Visitor.visitSymbolRecord(Obj.Record));
 }
 
-void MappingTraits<PdbModiStream>::mapping(IO &IO, PdbModiStream &Obj) {
+void MappingContextTraits<PdbModiStream, pdb::yaml::SerializationContext>::mapping(IO &IO, PdbModiStream &Obj, pdb::yaml::SerializationContext &Context) {
   IO.mapRequired("Signature", Obj.Signature);
-  IO.mapRequired("Records", Obj.Symbols);
+  IO.mapRequired("Records", Obj.Symbols, Context);
 }
 
-void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
+void MappingContextTraits<PdbDbiModuleInfo, pdb::yaml::SerializationContext>::mapping(IO &IO, PdbDbiModuleInfo &Obj, pdb::yaml::SerializationContext &Context) {
   IO.mapRequired("Module", Obj.Mod);
   IO.mapRequired("ObjFile", Obj.Obj);
   IO.mapOptional("SourceFiles", Obj.SourceFiles);
-  IO.mapOptional("Modi", Obj.Modi);
+  IO.mapOptionalWithContext("Modi", Obj.Modi, Context);
 }
 
 void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
index c5b49522b454f51e1ca0f1ceb0956a03736cda93..3b9b8e5c8134976c17f9f0ed4362580c68348622 100644 (file)
@@ -138,30 +138,30 @@ template <> struct MappingTraits<pdb::yaml::PdbInfoStream> {
   static void mapping(IO &IO, pdb::yaml::PdbInfoStream &Obj);
 };
 
-template <> struct MappingTraits<pdb::yaml::PdbDbiStream> {
-  static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj);
+template <> struct MappingContextTraits<pdb::yaml::PdbDbiStream, pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj, pdb::yaml::SerializationContext &Context);
 };
 
 template <>
-struct MappingContextTraits<pdb::yaml::PdbTpiStream, llvm::BumpPtrAllocator> {
+struct MappingContextTraits<pdb::yaml::PdbTpiStream, pdb::yaml::SerializationContext> {
   static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj,
-                      llvm::BumpPtrAllocator &Allocator);
+    pdb::yaml::SerializationContext &Context);
 };
 
 template <> struct MappingTraits<pdb::yaml::NamedStreamMapping> {
   static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj);
 };
 
-template <> struct MappingTraits<pdb::yaml::PdbSymbolRecord> {
-  static void mapping(IO &IO, pdb::yaml::PdbSymbolRecord &Obj);
+template <> struct MappingContextTraits<pdb::yaml::PdbSymbolRecord, pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbSymbolRecord &Obj, pdb::yaml::SerializationContext &Context);
 };
 
-template <> struct MappingTraits<pdb::yaml::PdbModiStream> {
-  static void mapping(IO &IO, pdb::yaml::PdbModiStream &Obj);
+template <> struct MappingContextTraits<pdb::yaml::PdbModiStream, pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbModiStream &Obj, pdb::yaml::SerializationContext &Context);
 };
 
-template <> struct MappingTraits<pdb::yaml::PdbDbiModuleInfo> {
-  static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj);
+template <> struct MappingContextTraits<pdb::yaml::PdbDbiModuleInfo, pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj, pdb::yaml::SerializationContext &Context);
 };
 
 template <>
index 210260a03b5fc850d80b3fc75f66744a815db9a7..431bf404fb04016e943bc4cfb970277775bc5133 100644 (file)
@@ -113,6 +113,7 @@ template <> struct ScalarEnumerationTraits<RegisterId> {
     for (const auto &E : RegNames) {
       io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value));
     }
+    io.enumFallback<Hex16>(Reg);
   }
 };