[llvm] r305037 - [CodeView] Support remaining debug subsection types

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 8 17:28:09 PDT 2017


Author: zturner
Date: Thu Jun  8 19:28:08 2017
New Revision: 305037

URL: http://llvm.org/viewvc/llvm-project?rev=305037&view=rev
Log:
[CodeView] Support remaining debug subsection types

This adds support for Symbols, StringTable, and FrameData subsection
types.  Even though these subsections rarely if ever appear in a PDB
file (they are usually in object files), there's no theoretical reason
why they *couldn't* appear in a PDB.  The real issue though is that in
order to add support for dumping and writing them (which will be useful
for object files), we need a way to test them.  And since there is no
support for reading and writing them to / from object files yet, making
PDB support them is the best way to both add support for the underlying
format and add support for tests at the same time.  Later, when we go
to add support for reading / writing them from object files, we'll need
only minimal changes in the underlying read/write code.

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializer.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
    llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
    llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
    llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
    llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
    llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
    llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
    llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp
    llvm/trunk/test/DebugInfo/PDB/Inputs/debug-subsections.yaml
    llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h Thu Jun  8 19:28:08 2017
@@ -45,6 +45,8 @@ public:
 
   bool valid() const { return Stream.valid(); }
 
+  BinaryStreamRef getBuffer() const { return Stream; }
+
 private:
   BinaryStreamRef Stream;
 };

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h Thu Jun  8 19:28:08 2017
@@ -52,7 +52,7 @@ public:
   DebugSubsectionRecordBuilder(std::unique_ptr<DebugSubsection> Subsection,
                                CodeViewContainer Container);
   uint32_t calculateSerializedLength();
-  Error commit(BinaryStreamWriter &Writer);
+  Error commit(BinaryStreamWriter &Writer) const;
 
 private:
   std::unique_ptr<DebugSubsection> Subsection;
@@ -66,14 +66,10 @@ template <> struct VarStreamArrayExtract
 
   static Error extract(BinaryStreamRef Stream, uint32_t &Length,
                        codeview::DebugSubsectionRecord &Info) {
-    // FIXME: We need to pass the container type through to this function, but
-    // VarStreamArray doesn't easily support stateful contexts.  In practice
-    // this isn't super important since the subsection header describes its
-    // length and we can just skip it.  It's more important when writing.
     if (auto EC = codeview::DebugSubsectionRecord::initialize(
             Stream, Info, codeview::CodeViewContainer::Pdb))
       return EC;
-    Length = Info.getRecordLength();
+    Length = alignTo(Info.getRecordLength(), 4);
     return Error::success();
   }
 };

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h Thu Jun  8 19:28:08 2017
@@ -24,8 +24,10 @@ class DebugSubsectionRecord;
 class DebugInlineeLinesSubsectionRef;
 class DebugCrossModuleExportsSubsectionRef;
 class DebugCrossModuleImportsSubsectionRef;
+class DebugFrameDataSubsectionRef;
 class DebugLinesSubsectionRef;
 class DebugStringTableSubsectionRef;
+class DebugSymbolsSubsectionRef;
 class DebugUnknownSubsectionRef;
 
 struct DebugSubsectionState {
@@ -97,6 +99,15 @@ public:
   virtual Error
   visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
                           const DebugSubsectionState &State) = 0;
+
+  virtual Error visitStringTable(DebugStringTableSubsectionRef &ST,
+                                 const DebugSubsectionState &State) = 0;
+
+  virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE,
+                             const DebugSubsectionState &State) = 0;
+
+  virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD,
+                               const DebugSubsectionState &State) = 0;
 };
 
 Error visitDebugSubsection(const DebugSubsectionRecord &R,

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h Thu Jun  8 19:28:08 2017
@@ -27,6 +27,9 @@ public:
 
   Error initialize(BinaryStreamReader Reader);
 
+  CVSymbolArray::Iterator begin() const { return Records.begin(); }
+  CVSymbolArray::Iterator end() const { return Records.end(); }
+
 private:
   CVSymbolArray Records;
 };

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializer.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializer.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializer.h Thu Jun  8 19:28:08 2017
@@ -86,6 +86,8 @@ public:
 
   void reset();
 
+  BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
   ArrayRef<ArrayRef<uint8_t>> records() const;
   TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
   TypeIndex insertRecord(const RemappedType &Record);

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h Thu Jun  8 19:28:08 2017
@@ -37,8 +37,9 @@ private:
   TypeSerializer Serializer;
 
 public:
-  explicit TypeTableBuilder(BumpPtrAllocator &Allocator)
-      : Allocator(Allocator), Serializer(Allocator) {}
+  explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
+                            bool WriteUnique = true)
+      : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
   TypeTableBuilder(const TypeTableBuilder &) = delete;
   TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
 

Modified: llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h Thu Jun  8 19:28:08 2017
@@ -26,6 +26,8 @@ namespace codeview {
 class DebugStringTableSubsection;
 class DebugStringTableSubsectionRef;
 class DebugChecksumsSubsectionRef;
+class DebugStringTableSubsection;
+class DebugChecksumsSubsection;
 }
 namespace CodeViewYAML {
 
@@ -33,6 +35,18 @@ namespace detail {
 struct YAMLSubsectionBase;
 }
 
+struct YAMLFrameData {
+  uint32_t RvaStart;
+  uint32_t CodeSize;
+  uint32_t LocalSize;
+  uint32_t ParamsSize;
+  uint32_t MaxStackSize;
+  StringRef FrameFunc;
+  uint32_t PrologSize;
+  uint32_t SavedRegsSize;
+  uint32_t Flags;
+};
+
 struct YAMLCrossModuleImport {
   StringRef ModuleName;
   std::vector<uint32_t> ImportIds;
@@ -97,8 +111,17 @@ struct YAMLDebugSubsection {
 };
 
 Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
-convertSubsectionList(ArrayRef<YAMLDebugSubsection> Subsections,
-                      codeview::DebugStringTableSubsection &Strings);
+toCodeViewSubsectionList(BumpPtrAllocator &Allocator,
+                         ArrayRef<YAMLDebugSubsection> Subsections,
+                         codeview::DebugStringTableSubsection &Strings);
+Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
+toCodeViewSubsectionList(
+    BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
+    std::unique_ptr<codeview::DebugStringTableSubsection> &TakeStrings,
+    codeview::DebugStringTableSubsection *StringsRef);
+
+std::unique_ptr<codeview::DebugStringTableSubsection>
+findStringTable(ArrayRef<YAMLDebugSubsection> Sections);
 
 } // namespace CodeViewYAML
 } // namespace llvm

Modified: llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h Thu Jun  8 19:28:08 2017
@@ -18,8 +18,12 @@
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Allocator.h"
 
 namespace llvm {
+namespace codeview {
+class TypeTableBuilder;
+}
 namespace CodeViewYAML {
 namespace detail {
 struct LeafRecordBase;
@@ -34,6 +38,7 @@ struct LeafRecord {
   std::shared_ptr<detail::LeafRecordBase> Leaf;
 
   codeview::CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const;
+  codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const;
   static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
 };
 } // namespace CodeViewYAML

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp Thu Jun  8 19:28:08 2017
@@ -24,7 +24,7 @@ Error DebugStringTableSubsectionRef::ini
   return Error::success();
 }
 Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
-  return Reader.readStreamRef(Stream, Reader.bytesRemaining());
+  return Reader.readStreamRef(Stream);
 }
 
 Expected<StringRef>
@@ -55,20 +55,19 @@ uint32_t DebugStringTableSubsection::cal
 }
 
 Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
-  assert(Writer.bytesRemaining() == StringSize);
-  uint32_t MaxOffset = 1;
+  uint32_t Begin = Writer.getOffset();
+  uint32_t End = Begin + StringSize;
 
   for (auto &Pair : Strings) {
     StringRef S = Pair.getKey();
-    uint32_t Offset = Pair.getValue();
+    uint32_t Offset = Begin + Pair.getValue();
     Writer.setOffset(Offset);
     if (auto EC = Writer.writeCString(S))
       return EC;
-    MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1);
+    assert(Writer.getOffset() <= End);
   }
 
-  Writer.setOffset(MaxOffset);
-  assert(Writer.bytesRemaining() == 0);
+  Writer.setOffset(End);
   return Error::success();
 }
 

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp Thu Jun  8 19:28:08 2017
@@ -40,6 +40,9 @@ Error DebugSubsectionRecord::initialize(
   case DebugSubsectionKind::InlineeLines:
   case DebugSubsectionKind::CrossScopeExports:
   case DebugSubsectionKind::CrossScopeImports:
+  case DebugSubsectionKind::Symbols:
+  case DebugSubsectionKind::StringTable:
+  case DebugSubsectionKind::FrameData:
     break;
   default:
     llvm_unreachable("Unexpected debug fragment kind!");
@@ -52,9 +55,7 @@ Error DebugSubsectionRecord::initialize(
 }
 
 uint32_t DebugSubsectionRecord::getRecordLength() const {
-  uint32_t Result = sizeof(DebugSubsectionHeader) + Data.getLength();
-  assert(Result % alignOf(Container) == 0);
-  return Result;
+  return sizeof(DebugSubsectionHeader) + Data.getLength();
 }
 
 DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
@@ -66,25 +67,29 @@ DebugSubsectionRecordBuilder::DebugSubse
     : Subsection(std::move(Subsection)), Container(Container) {}
 
 uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
-  uint32_t Size =
-      sizeof(DebugSubsectionHeader) +
-      alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
+  // The length of the entire subsection is always padded to 4 bytes, regardless
+  // of the container kind.
+  uint32_t Size = sizeof(DebugSubsectionHeader) +
+                  alignTo(Subsection->calculateSerializedSize(), 4);
   return Size;
 }
 
-Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) {
+Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
   assert(Writer.getOffset() % alignOf(Container) == 0 &&
          "Debug Subsection not properly aligned");
 
   DebugSubsectionHeader Header;
   Header.Kind = uint32_t(Subsection->kind());
-  Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader);
+  // The value written into the Header's Length field is only padded to the
+  // container's alignment
+  Header.Length =
+      alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
 
   if (auto EC = Writer.writeObject(Header))
     return EC;
   if (auto EC = Subsection->commit(Writer))
     return EC;
-  if (auto EC = Writer.padToAlignment(alignOf(Container)))
+  if (auto EC = Writer.padToAlignment(4))
     return EC;
 
   return Error::success();

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp Thu Jun  8 19:28:08 2017
@@ -1,4 +1,4 @@
-//===- DebugSubsectionVisitor.cpp ---------------------------*- C++ -*-===//
+//===- DebugSubsectionVisitor.cpp -------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -12,10 +12,12 @@
 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
 #include "llvm/Support/BinaryStreamReader.h"
 #include "llvm/Support/BinaryStreamRef.h"
@@ -91,6 +93,24 @@ Error llvm::codeview::visitDebugSubsecti
       return EC;
     return V.visitCrossModuleImports(Section, State);
   }
+  case DebugSubsectionKind::Symbols: {
+    DebugSymbolsSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitSymbols(Section, State);
+  }
+  case DebugSubsectionKind::StringTable: {
+    DebugStringTableSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitStringTable(Section, State);
+  }
+  case DebugSubsectionKind::FrameData: {
+    DebugFrameDataSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitFrameData(Section, State);
+  }
   default: {
     DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
     return V.visitUnknown(Fragment);

Modified: llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp Thu Jun  8 19:28:08 2017
@@ -20,13 +20,17 @@
 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::CodeViewYAML;
@@ -43,6 +47,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo
 LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
 LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
 
 LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
@@ -51,6 +56,7 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecks
 LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
 
 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
@@ -69,7 +75,8 @@ struct YAMLSubsectionBase {
 
   virtual void map(IO &IO) = 0;
   virtual std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *UseStrings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *UseStrings,
                        DebugChecksumsSubsection *UseChecksums) const = 0;
 };
 }
@@ -83,7 +90,8 @@ struct YAMLChecksumsSubsection : public
 
   void map(IO &IO) override;
   std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *Strings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
                        DebugChecksumsSubsection *Checksums) const override;
   static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
@@ -97,7 +105,8 @@ struct YAMLLinesSubsection : public YAML
 
   void map(IO &IO) override;
   std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *Strings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
                        DebugChecksumsSubsection *Checksums) const override;
   static Expected<std::shared_ptr<YAMLLinesSubsection>>
   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
@@ -113,7 +122,8 @@ struct YAMLInlineeLinesSubsection : publ
 
   void map(IO &IO) override;
   std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *Strings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
                        DebugChecksumsSubsection *Checksums) const override;
   static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
@@ -129,7 +139,8 @@ struct YAMLCrossModuleExportsSubsection
 
   void map(IO &IO) override;
   std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *Strings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
                        DebugChecksumsSubsection *Checksums) const override;
   static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
   fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
@@ -143,7 +154,8 @@ struct YAMLCrossModuleImportsSubsection
 
   void map(IO &IO) override;
   std::unique_ptr<DebugSubsection>
-  toCodeViewSubsection(DebugStringTableSubsection *Strings,
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
                        DebugChecksumsSubsection *Checksums) const override;
   static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
@@ -151,6 +163,51 @@ struct YAMLCrossModuleImportsSubsection
 
   std::vector<YAMLCrossModuleImport> Imports;
 };
+
+struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
+  YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
+
+  void map(IO &IO) override;
+  std::unique_ptr<DebugSubsection>
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
+                       DebugChecksumsSubsection *Checksums) const override;
+  static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
+  fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
+
+  std::vector<CodeViewYAML::SymbolRecord> Symbols;
+};
+
+struct YAMLStringTableSubsection : public YAMLSubsectionBase {
+  YAMLStringTableSubsection()
+      : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
+
+  void map(IO &IO) override;
+  std::unique_ptr<DebugSubsection>
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
+                       DebugChecksumsSubsection *Checksums) const override;
+  static Expected<std::shared_ptr<YAMLStringTableSubsection>>
+  fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
+
+  std::vector<StringRef> Strings;
+};
+
+struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
+  YAMLFrameDataSubsection()
+      : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
+
+  void map(IO &IO) override;
+  std::unique_ptr<DebugSubsection>
+  toCodeViewSubsection(BumpPtrAllocator &Allocator,
+                       DebugStringTableSubsection *Strings,
+                       DebugChecksumsSubsection *Checksums) const override;
+  static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
+  fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+                         const DebugFrameDataSubsectionRef &Frames);
+
+  std::vector<YAMLFrameData> Frames;
+};
 }
 
 void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
@@ -223,6 +280,17 @@ void MappingTraits<InlineeSite>::mapping
   IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
 }
 
+void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
+  IO.mapRequired("CodeSize", Obj.CodeSize);
+  IO.mapRequired("FrameFunc", Obj.FrameFunc);
+  IO.mapRequired("LocalSize", Obj.LocalSize);
+  IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
+  IO.mapOptional("ParamsSize", Obj.ParamsSize);
+  IO.mapOptional("PrologSize", Obj.PrologSize);
+  IO.mapOptional("RvaStart", Obj.RvaStart);
+  IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
+}
+
 void YAMLChecksumsSubsection::map(IO &IO) {
   IO.mapTag("!FileChecksums", true);
   IO.mapRequired("Checksums", Checksums);
@@ -254,6 +322,21 @@ void YAMLCrossModuleImportsSubsection::m
   IO.mapOptional("Imports", Imports);
 }
 
+void YAMLSymbolsSubsection::map(IO &IO) {
+  IO.mapTag("!Symbols", true);
+  IO.mapRequired("Records", Symbols);
+}
+
+void YAMLStringTableSubsection::map(IO &IO) {
+  IO.mapTag("!StringTable", true);
+  IO.mapRequired("Strings", Strings);
+}
+
+void YAMLFrameDataSubsection::map(IO &IO) {
+  IO.mapTag("!FrameData", true);
+  IO.mapRequired("Frames", Frames);
+}
+
 void MappingTraits<YAMLDebugSubsection>::mapping(
     IO &IO, YAMLDebugSubsection &Subsection) {
   if (!IO.outputting()) {
@@ -270,6 +353,12 @@ void MappingTraits<YAMLDebugSubsection>:
     } else if (IO.mapTag("!CrossModuleImports")) {
       Subsection.Subsection =
           std::make_shared<YAMLCrossModuleImportsSubsection>();
+    } else if (IO.mapTag("!Symbols")) {
+      Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
+    } else if (IO.mapTag("!StringTable")) {
+      Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
+    } else if (IO.mapTag("!FrameData")) {
+      Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
     } else {
       llvm_unreachable("Unexpected subsection tag!");
     }
@@ -289,7 +378,7 @@ findChecksums(ArrayRef<YAMLDebugSubsecti
 }
 
 std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
-    DebugStringTableSubsection *UseStrings,
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
     DebugChecksumsSubsection *UseChecksums) const {
   assert(UseStrings && !UseChecksums);
   auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
@@ -300,7 +389,7 @@ std::unique_ptr<DebugSubsection> YAMLChe
 }
 
 std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
-    DebugStringTableSubsection *UseStrings,
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
     DebugChecksumsSubsection *UseChecksums) const {
   assert(UseStrings && UseChecksums);
   auto Result =
@@ -331,7 +420,7 @@ std::unique_ptr<DebugSubsection> YAMLLin
 
 std::unique_ptr<DebugSubsection>
 YAMLInlineeLinesSubsection::toCodeViewSubsection(
-    DebugStringTableSubsection *UseStrings,
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
     DebugChecksumsSubsection *UseChecksums) const {
   assert(UseChecksums);
   auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
@@ -352,7 +441,7 @@ YAMLInlineeLinesSubsection::toCodeViewSu
 
 std::unique_ptr<DebugSubsection>
 YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
-    DebugStringTableSubsection *Strings,
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
     DebugChecksumsSubsection *Checksums) const {
   auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
   for (const auto &M : Exports)
@@ -362,7 +451,7 @@ YAMLCrossModuleExportsSubsection::toCode
 
 std::unique_ptr<DebugSubsection>
 YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
-    DebugStringTableSubsection *Strings,
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
     DebugChecksumsSubsection *Checksums) const {
   auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
   for (const auto &M : Imports) {
@@ -372,6 +461,47 @@ YAMLCrossModuleImportsSubsection::toCode
   return llvm::cast<DebugSubsection>(std::move(Result));
 }
 
+std::unique_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+    DebugChecksumsSubsection *Checksums) const {
+  auto Result = llvm::make_unique<DebugSymbolsSubsection>();
+  for (const auto &Sym : Symbols)
+    Result->addSymbol(
+        Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
+  return std::move(Result);
+}
+
+std::unique_ptr<DebugSubsection>
+YAMLStringTableSubsection::toCodeViewSubsection(
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+    DebugChecksumsSubsection *Checksums) const {
+  auto Result = llvm::make_unique<DebugStringTableSubsection>();
+  for (const auto &Str : this->Strings)
+    Result->insert(Str);
+  return std::move(Result);
+}
+
+std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
+    BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+    DebugChecksumsSubsection *Checksums) const {
+  assert(Strings);
+  auto Result = llvm::make_unique<DebugFrameDataSubsection>();
+  for (const auto &YF : Frames) {
+    codeview::FrameData F;
+    F.CodeSize = YF.CodeSize;
+    F.Flags = YF.Flags;
+    F.LocalSize = YF.LocalSize;
+    F.MaxStackSize = YF.MaxStackSize;
+    F.ParamsSize = YF.ParamsSize;
+    F.PrologSize = YF.PrologSize;
+    F.RvaStart = YF.RvaStart;
+    F.SavedRegsSize = YF.SavedRegsSize;
+    F.FrameFunc = Strings->insert(YF.FrameFunc);
+    Result->addFrameData(F);
+  }
+  return std::move(Result);
+}
+
 static Expected<SourceFileChecksumEntry>
 convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
                    const FileChecksumEntry &CS) {
@@ -503,9 +633,74 @@ YAMLCrossModuleImportsSubsection::fromCo
   return Result;
 }
 
+Expected<std::shared_ptr<YAMLSymbolsSubsection>>
+YAMLSymbolsSubsection::fromCodeViewSubsection(
+    const DebugSymbolsSubsectionRef &Symbols) {
+  auto Result = std::make_shared<YAMLSymbolsSubsection>();
+  for (const auto &Sym : Symbols) {
+    auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
+    if (!S)
+      return joinErrors(make_error<CodeViewError>(
+                            cv_error_code::corrupt_record,
+                            "Invalid CodeView Symbol Record in SymbolRecord "
+                            "subsection of .debug$S while converting to YAML!"),
+                        S.takeError());
+
+    Result->Symbols.push_back(*S);
+  }
+  return Result;
+}
+
+Expected<std::shared_ptr<YAMLStringTableSubsection>>
+YAMLStringTableSubsection::fromCodeViewSubsection(
+    const DebugStringTableSubsectionRef &Strings) {
+  auto Result = std::make_shared<YAMLStringTableSubsection>();
+  BinaryStreamReader Reader(Strings.getBuffer());
+  StringRef S;
+  // First item is a single null string, skip it.
+  if (auto EC = Reader.readCString(S))
+    return std::move(EC);
+  assert(S.empty());
+  while (Reader.bytesRemaining() > 0) {
+    if (auto EC = Reader.readCString(S))
+      return std::move(EC);
+    Result->Strings.push_back(S);
+  }
+  return Result;
+}
+
+Expected<std::shared_ptr<YAMLFrameDataSubsection>>
+YAMLFrameDataSubsection::fromCodeViewSubsection(
+    const DebugStringTableSubsectionRef &Strings,
+    const DebugFrameDataSubsectionRef &Frames) {
+  auto Result = std::make_shared<YAMLFrameDataSubsection>();
+  for (const auto &F : Frames) {
+    YAMLFrameData YF;
+    YF.CodeSize = F.CodeSize;
+    YF.Flags = F.Flags;
+    YF.LocalSize = F.LocalSize;
+    YF.MaxStackSize = F.MaxStackSize;
+    YF.ParamsSize = F.ParamsSize;
+    YF.PrologSize = F.PrologSize;
+    YF.RvaStart = F.RvaStart;
+    YF.SavedRegsSize = F.SavedRegsSize;
+
+    auto ES = Strings.getString(F.FrameFunc);
+    if (!ES)
+      return joinErrors(
+          make_error<CodeViewError>(
+              cv_error_code::no_records,
+              "Could not find string for string id while mapping FrameData!"),
+          ES.takeError());
+    YF.FrameFunc = *ES;
+    Result->Frames.push_back(YF);
+  }
+  return Result;
+}
+
 Expected<std::vector<std::unique_ptr<DebugSubsection>>>
-llvm::CodeViewYAML::convertSubsectionList(
-    ArrayRef<YAMLDebugSubsection> Subsections,
+llvm::CodeViewYAML::toCodeViewSubsectionList(
+    BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
     DebugStringTableSubsection &Strings) {
   std::vector<std::unique_ptr<DebugSubsection>> Result;
   if (Subsections.empty())
@@ -514,7 +709,8 @@ llvm::CodeViewYAML::convertSubsectionLis
   auto Checksums = findChecksums(Subsections);
   std::unique_ptr<DebugSubsection> ChecksumsBase;
   if (Checksums)
-    ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
+    ChecksumsBase =
+        Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr);
   DebugChecksumsSubsection *CS =
       static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
   for (const auto &SS : Subsections) {
@@ -524,7 +720,41 @@ llvm::CodeViewYAML::convertSubsectionLis
     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
       CVS = std::move(ChecksumsBase);
     else
-      CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS);
+      CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS);
+    assert(CVS != nullptr);
+    Result.push_back(std::move(CVS));
+  }
+  return std::move(Result);
+}
+
+Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
+llvm::CodeViewYAML::toCodeViewSubsectionList(
+    BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
+    std::unique_ptr<DebugStringTableSubsection> &TakeStrings,
+    DebugStringTableSubsection *StringsRef) {
+  std::vector<std::unique_ptr<DebugSubsection>> Result;
+  if (Subsections.empty())
+    return std::move(Result);
+
+  auto Checksums = findChecksums(Subsections);
+
+  std::unique_ptr<DebugSubsection> ChecksumsBase;
+  if (Checksums)
+    ChecksumsBase =
+        Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr);
+  DebugChecksumsSubsection *CS =
+      static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
+  for (const auto &SS : Subsections) {
+    // We've already converted the checksums and string table subsection, don't
+    // do it twice.
+    std::unique_ptr<DebugSubsection> CVS;
+    if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
+      CVS = std::move(ChecksumsBase);
+    else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) {
+      assert(TakeStrings && "No string table!");
+      CVS = std::move(TakeStrings);
+    } else
+      CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS);
     assert(CVS != nullptr);
     Result.push_back(std::move(CVS));
   }
@@ -546,6 +776,12 @@ struct SubsectionConversionVisitor : pub
                                 const DebugSubsectionState &State) override;
   Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
                                 const DebugSubsectionState &State) override;
+  Error visitStringTable(DebugStringTableSubsectionRef &ST,
+                         const DebugSubsectionState &State) override;
+  Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
+                     const DebugSubsectionState &State) override;
+  Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
+                       const DebugSubsectionState &State) override;
 
   YAMLDebugSubsection Subsection;
 };
@@ -607,6 +843,34 @@ Error SubsectionConversionVisitor::visit
   Subsection.Subsection = *Result;
   return Error::success();
 }
+
+Error SubsectionConversionVisitor::visitStringTable(
+    DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
+  auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
+  if (!Result)
+    return Result.takeError();
+  Subsection.Subsection = *Result;
+  return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitSymbols(
+    DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
+  auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
+  if (!Result)
+    return Result.takeError();
+  Subsection.Subsection = *Result;
+  return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitFrameData(
+    DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
+  auto Result =
+      YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
+  if (!Result)
+    return Result.takeError();
+  Subsection.Subsection = *Result;
+  return Error::success();
+}
 }
 
 Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
@@ -620,3 +884,18 @@ Expected<YAMLDebugSubsection> YAMLDebugS
 
   return V.Subsection;
 }
+
+std::unique_ptr<DebugStringTableSubsection>
+llvm::CodeViewYAML::findStringTable(ArrayRef<YAMLDebugSubsection> Sections) {
+  for (const auto &SS : Sections) {
+    if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
+      continue;
+
+    // String Table doesn't use the allocator.
+    BumpPtrAllocator Allocator;
+    auto Result =
+        SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr);
+    return llvm::cast<DebugStringTableSubsection>(std::move(Result));
+  }
+  return nullptr;
+}

Modified: llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp Thu Jun  8 19:28:08 2017
@@ -20,6 +20,7 @@
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -66,7 +67,7 @@ struct LeafRecordBase {
 
   virtual ~LeafRecordBase() {}
   virtual void map(yaml::IO &io) = 0;
-  virtual CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const = 0;
+  virtual CVType toCodeViewRecord(TypeTableBuilder &TTB) const = 0;
   virtual Error fromCodeViewRecord(CVType Type) = 0;
 };
 
@@ -80,10 +81,9 @@ template <typename T> struct LeafRecordI
     return TypeDeserializer::deserializeAs<T>(Type, Record);
   }
 
-  CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override {
-    TypeTableBuilder Table(Allocator);
-    Table.writeKnownType(Record);
-    return CVType(Kind, Table.records().front());
+  CVType toCodeViewRecord(TypeTableBuilder &TTB) const override {
+    TTB.writeKnownType(Record);
+    return CVType(Kind, TTB.records().back());
   }
 
   mutable T Record;
@@ -93,7 +93,7 @@ template <> struct LeafRecordImpl<FieldL
   explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}
 
   void map(yaml::IO &io) override;
-  CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override;
+  CVType toCodeViewRecord(TypeTableBuilder &TTB) const override;
   Error fromCodeViewRecord(CVType Type) override;
 
   std::vector<MemberRecord> Members;
@@ -440,16 +440,15 @@ Error LeafRecordImpl<FieldListRecord>::f
   return visitMemberRecordStream(Type.content(), V);
 }
 
-CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(
-    BumpPtrAllocator &Allocator) const {
-  TypeTableBuilder TTB(Allocator);
+CVType
+LeafRecordImpl<FieldListRecord>::toCodeViewRecord(TypeTableBuilder &TTB) const {
   FieldListRecordBuilder FLRB(TTB);
   FLRB.begin();
   for (const auto &Member : Members) {
     Member.Member->writeTo(FLRB);
   }
   FLRB.end(true);
-  return CVType(Kind, TTB.records().front());
+  return CVType(Kind, TTB.records().back());
 }
 
 void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {
@@ -634,8 +633,13 @@ Expected<LeafRecord> LeafRecord::fromCod
   return make_error<CodeViewError>(cv_error_code::corrupt_record);
 }
 
-CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Allocator) const {
-  return Leaf->toCodeViewRecord(Allocator);
+CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Alloc) const {
+  TypeTableBuilder TTB(Alloc);
+  return Leaf->toCodeViewRecord(TTB);
+}
+
+CVType LeafRecord::toCodeViewRecord(TypeTableBuilder &TTB) const {
+  return Leaf->toCodeViewRecord(TTB);
 }
 
 namespace llvm {

Modified: llvm/trunk/test/DebugInfo/PDB/Inputs/debug-subsections.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/debug-subsections.yaml?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/Inputs/debug-subsections.yaml (original)
+++ llvm/trunk/test/DebugInfo/PDB/Inputs/debug-subsections.yaml Thu Jun  8 19:28:08 2017
@@ -62,3 +62,30 @@ DbiStream:
             - FileName:        'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
               LineNum:         26950
               Inlinee:         22767
+    # The following subsections don't normally appear in PDB files, but we test
+    # them anyway
+    - Module:          'ObjFileSubsections'
+      ObjFile:         'ObjFileSubsections'
+      Subsections:
+        - !StringTable
+          Strings:
+            - 'String1'
+            - 'String2'
+            - 'String3'
+        - !Symbols
+          Records:
+            - Kind:            S_OBJNAME
+              ObjNameSym:
+                Signature:       0
+                ObjectName:      'ObjFileSubsections'
+        - !FrameData
+          Frames:
+            - CodeSize:           1
+              FrameFunc:          'MyFunc'
+              LocalSize:          2
+              MaxStackSize:       3
+              ParamsSize:         4
+              PrologSize:         5
+              RvaStart:           6
+              SavedRegsSize:      7
+...

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test Thu Jun  8 19:28:08 2017
@@ -1,5 +1,4 @@
 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
-
 ; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
 ; RUN: llvm-pdbdump raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
 
@@ -106,65 +105,106 @@ RAW-NEXT:           }
 RAW-NEXT:         ]
 RAW-NEXT:       ]
 RAW-NEXT:     }
-RAW-NEXT:    {
-RAW-NEXT:      Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-RAW:           Subsections [
-RAW-NEXT:        FileChecksums {
-RAW-NEXT:          Checksum {
-RAW-NEXT:            FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT:            Kind: MD5 (0x1)
-RAW-NEXT:            Checksum (
-RAW-NEXT:              0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC  |....>...)...&...|
-RAW-NEXT:            )
-RAW-NEXT:          }
-RAW-NEXT:          Checksum {
-RAW-NEXT:            FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT:            Kind: MD5 (0x1)
-RAW-NEXT:            Checksum (
-RAW-NEXT:              0000: 1154D69F 5B265019 6E1FC34F 4134E56B  |.T..[&P.n..OA4.k|
-RAW-NEXT:            )
-RAW-NEXT:          }
-RAW-NEXT:        }
-RAW-NEXT:        Lines {
-RAW-NEXT:          RelocSegment: 1
-RAW-NEXT:          RelocOffset: 16
-RAW-NEXT:          CodeSize: 10
-RAW-NEXT:          HasColumns: No
-RAW-NEXT:          FileEntry {
-RAW-NEXT:            FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT:            Line {
-RAW-NEXT:              Offset: 0
-RAW-NEXT:              LineNumberStart: 5
-RAW-NEXT:              EndDelta: 0
-RAW-NEXT:              IsStatement: Yes
-RAW-NEXT:            }
-RAW-NEXT:            Line {
-RAW-NEXT:              Offset: 3
-RAW-NEXT:              LineNumberStart: 6
-RAW-NEXT:              EndDelta: 0
-RAW-NEXT:              IsStatement: Yes
-RAW-NEXT:            }
-RAW-NEXT:            Line {
-RAW-NEXT:              Offset: 8
-RAW-NEXT:              LineNumberStart: 7
-RAW-NEXT:              EndDelta: 0
-RAW-NEXT:              IsStatement: Yes
-RAW-NEXT:            }
-RAW-NEXT:          }
-RAW-NEXT:        }
-RAW-NEXT:        InlineeLines {
-RAW-NEXT:          HasExtraFiles: No
-RAW-NEXT:          Lines [
-RAW-NEXT:            Inlinee {
-RAW-NEXT:              FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT:              Function {
-RAW-NEXT:                Index: 0x58ef (unknown function)
-RAW-NEXT:              }
-RAW-NEXT:              SourceLine: 26950
-RAW-NEXT:            }
-RAW-NEXT:          ]
-RAW-NEXT:        }
-RAW-NEXT:      ]
-RAW-NEXT:    }
-RAW-NEXT:  ]
-RAW-NEXT:}
+RAW-NEXT:     {
+RAW-NEXT:       Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
+RAW:            Subsections [
+RAW-NEXT:         FileChecksums {
+RAW-NEXT:           Checksum {
+RAW-NEXT:             FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+RAW-NEXT:             Kind: MD5 (0x1)
+RAW-NEXT:             Checksum (
+RAW-NEXT:               0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC  |....>...)...&...|
+RAW-NEXT:             )
+RAW-NEXT:           }
+RAW-NEXT:           Checksum {
+RAW-NEXT:             FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+RAW-NEXT:             Kind: MD5 (0x1)
+RAW-NEXT:             Checksum (
+RAW-NEXT:               0000: 1154D69F 5B265019 6E1FC34F 4134E56B  |.T..[&P.n..OA4.k|
+RAW-NEXT:             )
+RAW-NEXT:           }
+RAW-NEXT:         }
+RAW-NEXT:         Lines {
+RAW-NEXT:           RelocSegment: 1
+RAW-NEXT:           RelocOffset: 16
+RAW-NEXT:           CodeSize: 10
+RAW-NEXT:           HasColumns: No
+RAW-NEXT:           FileEntry {
+RAW-NEXT:             FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+RAW-NEXT:             Line {
+RAW-NEXT:               Offset: 0
+RAW-NEXT:               LineNumberStart: 5
+RAW-NEXT:               EndDelta: 0
+RAW-NEXT:               IsStatement: Yes
+RAW-NEXT:             }
+RAW-NEXT:             Line {
+RAW-NEXT:               Offset: 3
+RAW-NEXT:               LineNumberStart: 6
+RAW-NEXT:               EndDelta: 0
+RAW-NEXT:               IsStatement: Yes
+RAW-NEXT:             }
+RAW-NEXT:             Line {
+RAW-NEXT:               Offset: 8
+RAW-NEXT:               LineNumberStart: 7
+RAW-NEXT:               EndDelta: 0
+RAW-NEXT:               IsStatement: Yes
+RAW-NEXT:             }
+RAW-NEXT:           }
+RAW-NEXT:         }
+RAW-NEXT:         InlineeLines {
+RAW-NEXT:           HasExtraFiles: No
+RAW-NEXT:           Lines [
+RAW-NEXT:             Inlinee {
+RAW-NEXT:               FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+RAW-NEXT:               Function {
+RAW-NEXT:                 Index: 0x58ef (unknown function)
+RAW-NEXT:               }
+RAW-NEXT:               SourceLine: 26950
+RAW-NEXT:             }
+RAW-NEXT:           ]
+RAW-NEXT:         }
+RAW-NEXT:       ]
+RAW-NEXT:     }
+RAW-NEXT:     {
+RAW-NEXT:       Name: ObjFileSubsections
+RAW-NEXT:       Debug Stream Index: 11
+RAW-NEXT:       Object File Name: ObjFileSubsections
+RAW-NEXT:       Num Files: 0
+RAW-NEXT:       Source File Name Idx: 0
+RAW-NEXT:       Pdb File Name Idx: 0
+RAW-NEXT:       Line Info Byte Size: 0
+RAW-NEXT:       C13 Line Info Byte Size: 116
+RAW-NEXT:       Symbol Byte Size: 4
+RAW-NEXT:       Type Server Index: 0
+RAW-NEXT:       Has EC Info: No
+RAW-NEXT:       Subsections [
+RAW-NEXT:         String Table [
+RAW-NEXT:           String1
+RAW-NEXT:           String2
+RAW-NEXT:           String3
+RAW-NEXT:         ]
+RAW-NEXT:         Symbols [
+RAW-NEXT:           {
+RAW-NEXT:             ObjectName {
+RAW-NEXT:               Signature: 0x0
+RAW-NEXT:               ObjectName: ObjFileSubsections
+RAW-NEXT:             }
+RAW-NEXT:           }
+RAW-NEXT:         ]
+RAW-NEXT:         FrameData [
+RAW-NEXT:           Frame {
+RAW-NEXT:             Rva: 6
+RAW-NEXT:             CodeSize: 1
+RAW-NEXT:             LocalSize: 2
+RAW-NEXT:             ParamsSize: 4
+RAW-NEXT:             MaxStackSize: 3
+RAW-NEXT:             FrameFunc: MyFunc
+RAW-NEXT:             PrologSize: 5
+RAW-NEXT:             SavedRegsSize: 7
+RAW-NEXT:             Flags: 0
+RAW-NEXT:           }
+RAW-NEXT:         ]
+RAW-NEXT:       ]
+RAW-NEXT:     }
+RAW-NEXT:   ]
+RAW-NEXT: }

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Thu Jun  8 19:28:08 2017
@@ -17,9 +17,12 @@
 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -84,8 +87,9 @@ struct PageStats {
 
 class C13RawVisitor : public DebugSubsectionVisitor {
 public:
-  C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &IPI)
-      : P(P), IPI(IPI) {}
+  C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI,
+                LazyRandomTypeCollection &IPI)
+      : P(P), TPI(TPI), IPI(IPI) {}
 
   Error visitLines(DebugLinesSubsectionRef &Lines,
                    const DebugSubsectionState &State) override {
@@ -204,6 +208,72 @@ public:
     return Error::success();
   }
 
+  Error visitFrameData(DebugFrameDataSubsectionRef &FD,
+                       const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
+      return Error::success();
+
+    ListScope L(P, "FrameData");
+    for (const auto &Frame : FD) {
+      DictScope D(P, "Frame");
+      auto Name = getNameFromStringTable(Frame.FrameFunc, State);
+      if (!Name)
+        return joinErrors(make_error<RawError>(raw_error_code::invalid_format,
+                                               "Invalid Frame.FrameFunc index"),
+                          std::move(Name.takeError()));
+      P.printNumber("Rva", Frame.RvaStart);
+      P.printNumber("CodeSize", Frame.CodeSize);
+      P.printNumber("LocalSize", Frame.LocalSize);
+      P.printNumber("ParamsSize", Frame.ParamsSize);
+      P.printNumber("MaxStackSize", Frame.MaxStackSize);
+      P.printString("FrameFunc", *Name);
+      P.printNumber("PrologSize", Frame.PrologSize);
+      P.printNumber("SavedRegsSize", Frame.SavedRegsSize);
+      P.printNumber("Flags", Frame.Flags);
+    }
+    return Error::success();
+  }
+
+  Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
+                     const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
+      return Error::success();
+    ListScope L(P, "Symbols");
+
+    // This section should not actually appear in a PDB file, it really only
+    // appears in object files.  But we support it here for testing.  So we
+    // specify the Object File container type.
+    codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr,
+                                false);
+    for (auto S : Symbols) {
+      DictScope LL(P, "");
+      if (auto EC = SD.dump(S)) {
+        return make_error<RawError>(
+            raw_error_code::corrupt_file,
+            "DEBUG_S_SYMBOLS subsection contained corrupt symbol record");
+      }
+    }
+    return Error::success();
+  }
+
+  Error visitStringTable(DebugStringTableSubsectionRef &Strings,
+                         const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
+      return Error::success();
+
+    ListScope D(P, "String Table");
+    BinaryStreamReader Reader(Strings.getBuffer());
+    StringRef S;
+    consumeError(Reader.readCString(S));
+    while (Reader.bytesRemaining() > 0) {
+      consumeError(Reader.readCString(S));
+      if (S.empty() && Reader.bytesRemaining() < 4)
+        break;
+      P.printString(S);
+    }
+    return Error::success();
+  }
+
 private:
   Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
     CompactTypeDumpVisitor CTDV(IPI, Index, &P);
@@ -245,6 +315,7 @@ private:
   }
 
   ScopedPrinter &P;
+  LazyRandomTypeCollection &TPI;
   LazyRandomTypeCollection &IPI;
 };
 }
@@ -847,14 +918,14 @@ Error LLVMOutputStyle::dumpDbiStream() {
         if (auto EC = ModS.reload())
           return EC;
 
+        auto ExpectedTpi = initializeTypeDatabase(StreamTPI);
+        if (!ExpectedTpi)
+          return ExpectedTpi.takeError();
+        auto &Tpi = *ExpectedTpi;
         if (ShouldDumpSymbols) {
-          auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
-          if (!ExpectedTypes)
-            return ExpectedTypes.takeError();
-          auto &Types = *ExpectedTypes;
 
           ListScope SS(P, "Symbols");
-          codeview::CVSymbolDumper SD(P, Types, CodeViewContainer::Pdb, nullptr,
+          codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr,
                                       false);
           bool HadError = false;
           for (auto S : ModS.symbols(&HadError)) {
@@ -876,10 +947,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
         }
         if (!opts::shared::DumpModuleSubsections.empty()) {
           ListScope SS(P, "Subsections");
-          auto ExpectedTypes = initializeTypeDatabase(StreamIPI);
-          if (!ExpectedTypes)
-            return ExpectedTypes.takeError();
-          auto &IpiItems = *ExpectedTypes;
+          auto ExpectedIpi = initializeTypeDatabase(StreamIPI);
+          if (!ExpectedIpi)
+            return ExpectedIpi.takeError();
+          auto &Ipi = *ExpectedIpi;
           auto ExpectedStrings = File.getStringTable();
           if (!ExpectedStrings)
             return joinErrors(
@@ -887,7 +958,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
                                      "Could not get string table!"),
                 std::move(ExpectedStrings.takeError()));
 
-          C13RawVisitor V(P, IpiItems);
+          C13RawVisitor V(P, Tpi, Ipi);
           if (auto EC = codeview::visitDebugSubsections(
                   ModS.subsections(), V, ExpectedStrings->getStringTable()))
             return EC;

Modified: llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp?rev=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp Thu Jun  8 19:28:08 2017
@@ -171,6 +171,12 @@ static opts::ModuleSubsection convertSub
     return opts::ModuleSubsection::InlineeLines;
   case DebugSubsectionKind::Lines:
     return opts::ModuleSubsection::Lines;
+  case DebugSubsectionKind::Symbols:
+    return opts::ModuleSubsection::Symbols;
+  case DebugSubsectionKind::StringTable:
+    return opts::ModuleSubsection::StringTable;
+  case DebugSubsectionKind::FrameData:
+    return opts::ModuleSubsection::FrameData;
   default:
     return opts::ModuleSubsection::Unknown;
   }

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=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Thu Jun  8 19:28:08 2017
@@ -434,6 +434,14 @@ cl::list<ModuleSubsection> DumpModuleSub
                    "Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
         clEnumValN(ModuleSubsection::Lines, "lines",
                    "Lines (DEBUG_S_LINES subsection)"),
+        clEnumValN(ModuleSubsection::StringTable, "strings",
+                   "String Table (DEBUG_S_STRINGTABLE subsection) (not "
+                   "typically present in PDB file)"),
+        clEnumValN(ModuleSubsection::FrameData, "frames",
+                   "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
+        clEnumValN(ModuleSubsection::Symbols, "symbols",
+                   "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
+                   "present in PDB file)"),
         clEnumValN(ModuleSubsection::All, "all", "All known subsections")),
     cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand));
 cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
@@ -545,8 +553,8 @@ static void yamlToPdb(StringRef Path) {
       }
     }
 
-    auto CodeViewSubsections =
-        ExitOnErr(CodeViewYAML::convertSubsectionList(MI.Subsections, Strings));
+    auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
+        Allocator, MI.Subsections, Strings));
     for (auto &SS : CodeViewSubsections) {
       ModiBuilder.addDebugSubsection(std::move(SS));
     }

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=305037&r1=305036&r2=305037&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h Thu Jun  8 19:28:08 2017
@@ -34,6 +34,9 @@ enum class ModuleSubsection {
   InlineeLines,
   CrossScopeImports,
   CrossScopeExports,
+  StringTable,
+  Symbols,
+  FrameData,
   All
 };
 




More information about the llvm-commits mailing list