]> granicus.if.org Git - llvm/commitdiff
[PDB/CodeView] Read/write codeview inlinee line information.
authorZachary Turner <zturner@google.com>
Tue, 2 May 2017 16:56:09 +0000 (16:56 +0000)
committerZachary Turner <zturner@google.com>
Tue, 2 May 2017 16:56:09 +0000 (16:56 +0000)
Previously we wrote line information and file checksum
information, but we did not write information about inlinee
lines and functions.  This patch adds support for that.

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

24 files changed:
include/llvm/DebugInfo/CodeView/Line.h
include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h
include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h [new file with mode: 0644]
include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
include/llvm/Support/BinaryStreamWriter.h
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
lib/DebugInfo/CodeView/CMakeLists.txt
lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp
lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp
lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp
lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp [new file with mode: 0644]
lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
test/DebugInfo/PDB/Inputs/simple-line-info.yaml
test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test
tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp
tools/llvm-pdbdump/C13DebugFragmentVisitor.h
tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp
tools/llvm-pdbdump/CompactTypeDumpVisitor.h
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
tools/llvm-readobj/COFFDumper.cpp

index cb29aa2489ec2adde33e8c8fb53af0c0b7c6caa0..ac229c3375137dda10dd88a80df18664d6604a3a 100644 (file)
@@ -127,20 +127,6 @@ public:
   bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
 };
 
-enum class InlineeLinesSignature : uint32_t {
-  Normal,    // CV_INLINEE_SOURCE_LINE_SIGNATURE
-  ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
-};
-
-struct InlineeSourceLine {
-  TypeIndex Inlinee;         // ID of the function that was inlined.
-  ulittle32_t FileID;        // Offset into FileChecksums subsection.
-  ulittle32_t SourceLineNum; // First line of inlined code.
-  // If extra files present:
-  //   ulittle32_t ExtraFileCount;
-  //   ulittle32_t Files[];
-};
-
 } // namespace codeview
 } // namespace llvm
 
index 90da3e03a1586aad9a4a4dd7b02145c96c8c377e..1f55d2024203aa4ceccbdec53675203ce2bf8e34 100644 (file)
@@ -39,6 +39,10 @@ public:
     return Error::success();
   }
 
+  virtual Error visitInlineeLines(ModuleDebugInlineeLineFragmentRef &Inlinees) {
+    return Error::success();
+  }
+
   virtual Error finished() { return Error::success(); }
 };
 
diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h
new file mode 100644 (file)
index 0000000..177367c
--- /dev/null
@@ -0,0 +1,103 @@
+//===- ModuleDebugInlineeLinesFragment.h ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H
+#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H
+
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+
+class ModuleDebugInlineeLineFragmentRef;
+
+enum class InlineeLinesSignature : uint32_t {
+  Normal,    // CV_INLINEE_SOURCE_LINE_SIGNATURE
+  ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
+};
+
+struct InlineeSourceLineHeader {
+  TypeIndex Inlinee;                  // ID of the function that was inlined.
+  support::ulittle32_t FileID;        // Offset into FileChecksums subsection.
+  support::ulittle32_t SourceLineNum; // First line of inlined code.
+                                      // If extra files present:
+                                      //   ulittle32_t ExtraFileCount;
+                                      //   ulittle32_t Files[];
+};
+
+struct InlineeSourceLine {
+  const InlineeSourceLineHeader *Header;
+  FixedStreamArray<support::ulittle32_t> ExtraFiles;
+};
+}
+
+template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> {
+  typedef codeview::ModuleDebugInlineeLineFragmentRef ContextType;
+
+  static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+                       codeview::InlineeSourceLine &Item,
+                       ContextType *Fragment);
+};
+
+namespace codeview {
+class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef {
+  typedef VarStreamArray<InlineeSourceLine> LinesArray;
+  typedef LinesArray::Iterator Iterator;
+
+public:
+  ModuleDebugInlineeLineFragmentRef();
+
+  static bool classof(const ModuleDebugFragmentRef *S) {
+    return S->kind() == ModuleDebugFragmentKind::InlineeLines;
+  }
+
+  Error initialize(BinaryStreamReader Reader);
+  bool hasExtraFiles() const;
+
+  Iterator begin() const { return Lines.begin(); }
+  Iterator end() const { return Lines.end(); }
+
+private:
+  InlineeLinesSignature Signature;
+  VarStreamArray<InlineeSourceLine> Lines;
+};
+
+class ModuleDebugInlineeLineFragment final : public ModuleDebugFragment {
+public:
+  explicit ModuleDebugInlineeLineFragment(bool HasExtraFiles);
+
+  static bool classof(const ModuleDebugFragment *S) {
+    return S->kind() == ModuleDebugFragmentKind::InlineeLines;
+  }
+
+  Error commit(BinaryStreamWriter &Writer) override;
+  uint32_t calculateSerializedLength() override;
+
+  void addInlineSite(TypeIndex FuncId, uint32_t FileOffset,
+                     uint32_t SourceLine);
+  void addExtraFile(uint32_t FileOffset);
+
+private:
+  bool HasExtraFiles = false;
+  uint32_t ExtraFileCount = 0;
+
+  struct Entry {
+    std::vector<support::ulittle32_t> ExtraFiles;
+    InlineeSourceLineHeader Header;
+  };
+  std::vector<Entry> Entries;
+};
+}
+}
+
+#endif
index 582e0485715b24f834604f611babf682049b1c9d..8cc5db981f5656bd3e063e51974fee5d6f5e16c2 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
@@ -48,8 +49,9 @@ public:
   void setObjFileName(StringRef Name);
   void addSymbol(codeview::CVSymbol Symbol);
 
-  void
-  addC13LineFragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+  void addC13Fragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+  void addC13Fragment(
+      std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees);
   void setC13FileChecksums(
       std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> Checksums);
 
@@ -80,8 +82,11 @@ private:
   std::string ObjFileName;
   std::vector<std::string> SourceFiles;
   std::vector<codeview::CVSymbol> Symbols;
-  std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
+
   std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> ChecksumInfo;
+  std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
+  std::vector<std::unique_ptr<codeview::ModuleDebugInlineeLineFragment>>
+      Inlinees;
 
   std::vector<std::unique_ptr<codeview::ModuleDebugFragmentRecordBuilder>>
       C13Builders;
index 64f26b24543df3a545991993e1b8a9b8af54e176..6734a797ccc4408a07db8212bb8f92de7da72920 100644 (file)
@@ -30,6 +30,8 @@ namespace llvm {
 /// although no methods are overridable.
 class BinaryStreamWriter {
 public:
+  // FIXME: We should be able to slice and drop_front etc on Writers / Readers.
+
   BinaryStreamWriter() = default;
   explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
   virtual ~BinaryStreamWriter() {}
index 4bfe3bf2b633fcf9045e552b5b95e441a3ae2775..786b11618d75bda80b3ecb882337d711e34d07e4 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
index 7655f6c651ed1cfc66a14091914f73b120059582..421f22ca5d8d7aff766cb2ae3a6425a2e0d10fea 100644 (file)
@@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   ModuleDebugFragment.cpp
   ModuleDebugFragmentRecord.cpp
   ModuleDebugFragmentVisitor.cpp
+  ModuleDebugInlineeLinesFragment.cpp
   ModuleDebugLineFragment.cpp
   ModuleDebugUnknownFragment.cpp
   RecordSerialization.cpp
index 79e5b9d690de6865a7a24352955eb1253c6df46f..c349e7ecce9611b4e4a40155835485e5bcc8633f 100644 (file)
@@ -68,7 +68,10 @@ void ModuleDebugFileChecksumFragment::addChecksum(uint32_t StringTableOffset,
   // This maps the offset of this string in the string table to the offset
   // of this checksum entry in the checksum buffer.
   OffsetMap[StringTableOffset] = SerializedSize;
-  SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
+  assert(SerializedSize % 4 == 0);
+
+  uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
+  SerializedSize += Len;
 }
 
 uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
@@ -85,6 +88,8 @@ Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) {
       return EC;
     if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
       return EC;
+    if (auto EC = Writer.padToAlignment(4))
+      return EC;
   }
   return Error::success();
 }
index 263b632da3f41a471788db63930fb9cbb009f6c8..b2543de78069910ad2507f932392a558396c92e6 100644 (file)
@@ -34,6 +34,7 @@ Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream,
   switch (Kind) {
   case ModuleDebugFragmentKind::FileChecksums:
   case ModuleDebugFragmentKind::Lines:
+  case ModuleDebugFragmentKind::InlineeLines:
     break;
   default:
     llvm_unreachable("Unexpected debug fragment kind!");
index b7a86ee66994a1563317879d0b73976aeebeae76..dc591f3990e2761cde29463dae400f5bcbcfa371 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
 #include "llvm/Support/BinaryStreamReader.h"
@@ -37,6 +38,12 @@ Error llvm::codeview::visitModuleDebugFragment(
 
     return V.visitFileChecksums(Fragment);
   }
+  case ModuleDebugFragmentKind::InlineeLines: {
+    ModuleDebugInlineeLineFragmentRef Fragment;
+    if (auto EC = Fragment.initialize(Reader))
+      return EC;
+    return V.visitInlineeLines(Fragment);
+  }
   default: {
     ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData());
     return V.visitUnknown(Fragment);
diff --git a/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp b/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp
new file mode 100644 (file)
index 0000000..483f7cb
--- /dev/null
@@ -0,0 +1,116 @@
+//===- ModuleDebugInlineeLineFragment.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/ModuleDebugInlineeLinesFragment.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error VarStreamArrayExtractor<InlineeSourceLine>::extract(
+    BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item,
+    ContextType *Fragment) {
+  BinaryStreamReader Reader(Stream);
+
+  if (auto EC = Reader.readObject(Item.Header))
+    return EC;
+
+  if (Fragment->hasExtraFiles()) {
+    uint32_t ExtraFileCount;
+    if (auto EC = Reader.readInteger(ExtraFileCount))
+      return EC;
+    if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
+      return EC;
+  }
+
+  Len = Reader.getOffset();
+  return Error::success();
+}
+
+ModuleDebugInlineeLineFragmentRef::ModuleDebugInlineeLineFragmentRef()
+    : ModuleDebugFragmentRef(ModuleDebugFragmentKind::InlineeLines) {}
+
+Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) {
+  if (auto EC = Reader.readEnum(Signature))
+    return EC;
+
+  if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining(), this))
+    return EC;
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+bool ModuleDebugInlineeLineFragmentRef::hasExtraFiles() const {
+  return Signature == InlineeLinesSignature::ExtraFiles;
+}
+
+ModuleDebugInlineeLineFragment::ModuleDebugInlineeLineFragment(
+    bool HasExtraFiles)
+    : ModuleDebugFragment(ModuleDebugFragmentKind::InlineeLines),
+      HasExtraFiles(HasExtraFiles) {}
+
+uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() {
+  // 4 bytes for the signature
+  uint32_t Size = sizeof(InlineeLinesSignature);
+
+  // one header for each entry.
+  Size += Entries.size() * sizeof(InlineeSourceLineHeader);
+  if (HasExtraFiles) {
+    // If extra files are enabled, one count for each entry.
+    Size += Entries.size() * sizeof(uint32_t);
+
+    // And one file id for each file.
+    Size += ExtraFileCount * sizeof(uint32_t);
+  }
+  assert(Size % 4 == 0);
+  return Size;
+}
+
+Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) {
+  InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
+  if (HasExtraFiles)
+    Sig = InlineeLinesSignature::ExtraFiles;
+
+  if (auto EC = Writer.writeEnum(Sig))
+    return EC;
+
+  for (const auto &E : Entries) {
+    if (auto EC = Writer.writeObject(E.Header))
+      return EC;
+
+    if (!HasExtraFiles)
+      continue;
+
+    if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
+      return EC;
+  }
+
+  return Error::success();
+}
+
+void ModuleDebugInlineeLineFragment::addExtraFile(uint32_t FileOffset) {
+  auto &Entry = Entries.back();
+  Entry.ExtraFiles.push_back(ulittle32_t(FileOffset));
+  ++ExtraFileCount;
+}
+
+void ModuleDebugInlineeLineFragment::addInlineSite(TypeIndex FuncId,
+                                                   uint32_t FileOffset,
+                                                   uint32_t SourceLine) {
+  Entries.emplace_back();
+  auto &Entry = Entries.back();
+  Entry.Header.FileID = FileOffset;
+  Entry.Header.SourceLineNum = SourceLine;
+  Entry.Header.Inlinee = FuncId;
+}
index 41cb23a188fda44babfac3395e72cc13bcf4fc7c..f994b4538ef083db484491a2fd0e473baa457b93 100644 (file)
@@ -161,7 +161,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
   return Error::success();
 }
 
-void DbiModuleDescriptorBuilder::addC13LineFragment(
+void DbiModuleDescriptorBuilder::addC13Fragment(
     std::unique_ptr<ModuleDebugLineFragment> Lines) {
   ModuleDebugLineFragment &Frag = *Lines;
 
@@ -175,6 +175,20 @@ void DbiModuleDescriptorBuilder::addC13LineFragment(
       llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
 }
 
+void DbiModuleDescriptorBuilder::addC13Fragment(
+    std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees) {
+  ModuleDebugInlineeLineFragment &Frag = *Inlinees;
+
+  // File Checksums have to come first, so push an empty entry on if this
+  // is the first.
+  if (C13Builders.empty())
+    C13Builders.push_back(nullptr);
+
+  this->Inlinees.push_back(std::move(Inlinees));
+  C13Builders.push_back(
+      llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+}
+
 void DbiModuleDescriptorBuilder::setC13FileChecksums(
     std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
   assert(!ChecksumInfo && "Can't have more than one checksum info!");
index 71ce0545d5c2dc12dabe58c4b5e0bb93225da67e..66030020f8f4959254fc075cb27b410fe2f15617 100644 (file)
@@ -1,8 +1,4 @@
 ---
-StringTable:
-  - 'junk_a'
-  - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
-  - 'junk_b'
 DbiStream:
   Modules:
     - Module:          'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
@@ -14,6 +10,9 @@ DbiStream:
           - FileName:        'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
             Kind:            MD5
             Checksum:        A0A5BD0D3ECD93FC29D19DE826FBF4BC
+          - FileName:        'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
+            Kind:            MD5
+            Checksum:        1154D69F5B2650196E1FC34F4134E56B
         Lines:
           - CodeSize:        10
             Flags:           [  ]
@@ -35,4 +34,10 @@ DbiStream:
                     IsStatement:     true
                     EndDelta:        0
                 Columns:
+        InlineeLines:    
+          - HasExtraFiles:   false
+            Sites:           
+              - FileName:        'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
+                LineNum:         26950
+                Inlinee:         22767
 ...
index 8e1fc01290cbde0422f44c88bf408c5dd7fee837..1d63c85352aa63b931b9b3e97c59ab982e05c424 100644 (file)
@@ -18,6 +18,13 @@ LINES-NEXT:            Checksum (
 LINES-NEXT:              0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC  |....>...)...&...|
 LINES-NEXT:            )
 LINES-NEXT:          }
+LINES-NEXT:          Checksum {
+LINES-NEXT:            FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+LINES-NEXT:            Kind: MD5 (0x1)
+LINES-NEXT:            Checksum (
+LINES-NEXT:              0000: 1154D69F 5B265019 6E1FC34F 4134E56B  |.T..[&P.n..OA4.k|
+LINES-NEXT:            )
+LINES-NEXT:          }
 LINES-NEXT:        }
 LINES-NEXT:        Lines {
 LINES-NEXT:          Block {
@@ -48,5 +55,17 @@ LINES-NEXT:              }
 LINES-NEXT:            }
 LINES-NEXT:          }
 LINES-NEXT:        }
+LINES-NEXT:        InlineeLines {
+LINES-NEXT:          HasExtraFiles: No
+LINES-NEXT:          Lines [
+LINES-NEXT:            Inlinee {
+LINES-NEXT:              FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+LINES-NEXT:              Function {
+LINES-NEXT:                Index: 0x58ef (unknown function)
+LINES-NEXT:              }
+LINES-NEXT:              SourceLine: 26950
+LINES-NEXT:            }
+LINES-NEXT:          ]
+LINES-NEXT:        }
 LINES-NEXT:      ]
 LINES-NEXT:    }
index 940b38c4a8ce81fde8b9e5aa9e3c2a06a2234ecb..7c680ebb94cfd56fcb4e329ae7a73a0fd7ce4267 100644 (file)
@@ -10,6 +10,7 @@
 #include "C13DebugFragmentVisitor.h"
 
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/RawError.h"
@@ -41,6 +42,12 @@ Error C13DebugFragmentVisitor::visitLines(
   return Error::success();
 }
 
+Error C13DebugFragmentVisitor::visitInlineeLines(
+    codeview::ModuleDebugInlineeLineFragmentRef &Lines) {
+  this->InlineeLines.push_back(Lines);
+  return Error::success();
+}
+
 Error C13DebugFragmentVisitor::finished() {
   if (!Checksums.hasValue()) {
     assert(Lines.empty());
@@ -52,6 +59,9 @@ Error C13DebugFragmentVisitor::finished() {
   if (auto EC = handleLines())
     return EC;
 
+  if (auto EC = handleInlineeLines())
+    return EC;
+
   return Error::success();
 }
 
index f0a536c6adca27c0d8ba2468cc2e4ed4c6c02187..1054b0c9f6e0ac5cdb9e2fa6a8bc7919411a07a8 100644 (file)
@@ -35,16 +35,21 @@ public:
 
   Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final;
 
+  Error
+  visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final;
+
   Error finished() final;
 
 protected:
   virtual Error handleFileChecksums() { return Error::success(); }
   virtual Error handleLines() { return Error::success(); }
+  virtual Error handleInlineeLines() { return Error::success(); }
 
   Expected<StringRef> getNameFromStringTable(uint32_t Offset);
   Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
 
   Optional<codeview::ModuleDebugFileChecksumFragmentRef> Checksums;
+  std::vector<codeview::ModuleDebugInlineeLineFragmentRef> InlineeLines;
   std::vector<codeview::ModuleDebugLineFragmentRef> Lines;
 
   PDBFile &F;
index 1fc8dd5d51f0a65d93595cc4f0d9888e86373226..5ad0bfad26c19c53f4a002fd591c93dbcd36c46d 100644 (file)
@@ -31,14 +31,15 @@ static StringRef getLeafName(TypeLeafKind K) {
 
 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
                                                ScopedPrinter *W)
-    : W(W), TI(TypeIndex::None()), Offset(0), TypeDB(TypeDB) {}
+    : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
+                             W) {}
 
-Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
-  if (TI == TypeIndex::None())
-    TI.setIndex(TypeIndex::FirstNonSimpleIndex);
-  else
-    TI.setIndex(TI.getIndex() + 1);
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
+                                               TypeIndex FirstTI,
+                                               ScopedPrinter *W)
+    : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
 
+Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
   return Error::success();
 }
 
@@ -52,6 +53,7 @@ Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
           .str());
 
   Offset += Record.length();
+  TI.setIndex(TI.getIndex() + 1);
 
   return Error::success();
 }
index 180eea7b8d6a14fd6778961eb251302cc10058f6..76fafc93e030db7e7759e198f6180e925791efe0 100644 (file)
@@ -27,6 +27,8 @@ namespace pdb {
 class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
 public:
   CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
+  CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
+                         codeview::TypeIndex FirstTI, ScopedPrinter *W);
 
   /// Paired begin/end actions for all types. Receives all record data,
   /// including the fixed-length record prefix.
index 833cd810468263008c140f9a60187c8715e8a968..f3e28e0b08fc592b42c439b8e221ee138a86ec77 100644 (file)
@@ -20,6 +20,7 @@
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
@@ -82,10 +83,13 @@ struct PageStats {
 
 class C13RawVisitor : public C13DebugFragmentVisitor {
 public:
-  C13RawVisitor(ScopedPrinter &P, PDBFile &F)
-      : C13DebugFragmentVisitor(F), P(P) {}
+  C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
+      : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
 
   Error handleLines() override {
+    if (Lines.empty())
+      return Error::success();
+
     DictScope DD(P, "Lines");
 
     for (const auto &Fragment : Lines) {
@@ -126,6 +130,9 @@ public:
   }
 
   Error handleFileChecksums() override {
+    if (!Checksums.hasValue())
+      return Error::success();
+
     DictScope DD(P, "FileChecksums");
     for (const auto &CS : *Checksums) {
       DictScope DDD(P, "Checksum");
@@ -139,7 +146,50 @@ public:
     return Error::success();
   }
 
+  Error handleInlineeLines() override {
+    if (InlineeLines.empty())
+      return Error::success();
+
+    DictScope D(P, "InlineeLines");
+    for (const auto &IL : InlineeLines) {
+      P.printBoolean("HasExtraFiles", IL.hasExtraFiles());
+      ListScope LS(P, "Lines");
+      for (const auto &L : IL) {
+        DictScope DDD(P, "Inlinee");
+        if (auto EC = printFileName("FileName", L.Header->FileID))
+          return EC;
+
+        if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
+          return EC;
+        P.printNumber("SourceLine", L.Header->SourceLineNum);
+        if (IL.hasExtraFiles()) {
+          ListScope DDDD(P, "ExtraFiles");
+          for (const auto &EF : L.ExtraFiles) {
+            if (auto EC = printFileName("File", EF))
+              return EC;
+          }
+        }
+      }
+    }
+    return Error::success();
+  }
+
 private:
+  Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
+    CompactTypeDumpVisitor CTDV(DB, Index, &P);
+    CVTypeVisitor Visitor(CTDV);
+    DictScope D(P, Label);
+    if (DB.containsTypeIndex(Index)) {
+      CVType &Type = DB.getTypeRecord(Index);
+      if (auto EC = Visitor.visitTypeRecord(Type))
+        return EC;
+    } else {
+      P.printString(
+          llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
+              .str());
+    }
+    return Error::success();
+  }
   Error printFileName(StringRef Label, uint32_t Offset) {
     if (auto Result = getNameFromChecksumsBuffer(Offset)) {
       P.printString(Label, *Result);
@@ -149,6 +199,7 @@ private:
   }
 
   ScopedPrinter &P;
+  TypeDatabase &IPI;
 };
 }
 
@@ -618,6 +669,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
 
     if (auto EC = Visitor.visitTypeRecord(Type))
       return EC;
+    T.setIndex(T.getIndex() + 1);
   }
   if (HadError)
     return make_error<RawError>(raw_error_code::corrupt_file,
@@ -750,7 +802,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
         if (opts::raw::DumpLineInfo) {
           ListScope SS(P, "LineInfo");
 
-          C13RawVisitor V(P, File);
+          C13RawVisitor V(P, File, ItemDB);
           if (auto EC = codeview::visitModuleDebugFragments(
                   ModS.linesAndChecksums(), V))
             return EC;
index 645f2dc607dea7093c1de8256f76b3cf55500d7f..d6ba7d64545934bd375d44dfd07597cd9b6837e3 100644 (file)
@@ -41,6 +41,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineEntry)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceColumnEntry)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineBlock)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeSite)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeInfo)
 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)
@@ -336,6 +338,7 @@ void MappingContextTraits<pdb::yaml::PdbSourceLineInfo,
     mapping(IO &IO, PdbSourceLineInfo &Obj,
             pdb::yaml::SerializationContext &Context) {
   IO.mapRequired("CodeSize", Obj.CodeSize);
+
   IO.mapRequired("Flags", Obj.Flags);
   IO.mapRequired("RelocOffset", Obj.RelocOffset);
   IO.mapRequired("RelocSegment", Obj.RelocSegment);
@@ -348,6 +351,21 @@ void MappingContextTraits<pdb::yaml::PdbSourceFileInfo,
             pdb::yaml::SerializationContext &Context) {
   IO.mapOptionalWithContext("Checksums", Obj.FileChecksums, Context);
   IO.mapOptionalWithContext("Lines", Obj.LineFragments, Context);
+  IO.mapOptionalWithContext("InlineeLines", Obj.Inlinees, Context);
+}
+
+void MappingContextTraits<PdbInlineeSite, SerializationContext>::mapping(
+    IO &IO, PdbInlineeSite &Obj, SerializationContext &Context) {
+  IO.mapRequired("FileName", Obj.FileName);
+  IO.mapRequired("LineNum", Obj.SourceLineNum);
+  IO.mapRequired("Inlinee", Obj.Inlinee);
+  IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
+}
+
+void MappingContextTraits<PdbInlineeInfo, SerializationContext>::mapping(
+    IO &IO, PdbInlineeInfo &Obj, SerializationContext &Context) {
+  IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles);
+  IO.mapRequired("Sites", Obj.Sites, Context);
 }
 
 void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
index a998eafbb05841b3a415c07bf1c8c808dda66a59..423845caeb3175070c8ef9729b8b4491c973194a 100644 (file)
@@ -102,9 +102,22 @@ struct PdbSourceLineInfo {
   std::vector<PdbSourceLineBlock> Blocks;
 };
 
+struct PdbInlineeSite {
+  codeview::TypeIndex Inlinee;
+  StringRef FileName;
+  uint32_t SourceLineNum;
+  std::vector<StringRef> ExtraFiles;
+};
+
+struct PdbInlineeInfo {
+  bool HasExtraFiles;
+  std::vector<PdbInlineeSite> Sites;
+};
+
 struct PdbSourceFileInfo {
   std::vector<PdbSourceFileChecksumEntry> FileChecksums;
   std::vector<PdbSourceLineInfo> LineFragments;
+  std::vector<PdbInlineeInfo> Inlinees;
 };
 
 struct PdbDbiModuleInfo {
@@ -258,6 +271,20 @@ struct MappingContextTraits<pdb::yaml::PdbSourceFileInfo,
                       pdb::yaml::SerializationContext &Context);
 };
 
+template <>
+struct MappingContextTraits<pdb::yaml::PdbInlineeInfo,
+                            pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbInlineeInfo &Obj,
+                      pdb::yaml::SerializationContext &Context);
+};
+
+template <>
+struct MappingContextTraits<pdb::yaml::PdbInlineeSite,
+                            pdb::yaml::SerializationContext> {
+  static void mapping(IO &IO, pdb::yaml::PdbInlineeSite &Obj,
+                      pdb::yaml::SerializationContext &Context);
+};
+
 template <>
 struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
                             pdb::yaml::SerializationContext> {
index 18596a68a3cfbcc4eabeae686c98a60768358f3e..807d7f8b82e1e49e0c9eb1bb0c96ab50b9eb3cbe 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@@ -150,6 +151,35 @@ public:
     return Error::success();
   }
 
+  Error handleInlineeLines() override {
+    for (const auto &ILF : InlineeLines) {
+      Info.Inlinees.emplace_back();
+      auto &Inlinee = Info.Inlinees.back();
+
+      Inlinee.HasExtraFiles = ILF.hasExtraFiles();
+      for (const auto &IL : ILF) {
+        Inlinee.Sites.emplace_back();
+        auto &Site = Inlinee.Sites.back();
+        if (auto Result = getNameFromChecksumsBuffer(IL.Header->FileID))
+          Site.FileName = *Result;
+        else
+          return Result.takeError();
+
+        Site.Inlinee = IL.Header->Inlinee;
+        Site.SourceLineNum = IL.Header->SourceLineNum;
+        if (ILF.hasExtraFiles()) {
+          for (const auto &EF : IL.ExtraFiles) {
+            if (auto Result = getNameFromChecksumsBuffer(EF))
+              Site.ExtraFiles.push_back(*Result);
+            else
+              return Result.takeError();
+          }
+        }
+      }
+    }
+    return Error::success();
+  }
+
 private:
 
   llvm::pdb::yaml::PdbSourceFileInfo &Info;
index 0bbc49eadbb1b8e7da47d6ac50b83222a1e6b0db..642e169613ba7d767e515af6fd17eb6f5ca51a1b 100644 (file)
@@ -31,6 +31,9 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/config.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
 #include "llvm/DebugInfo/PDB/GenericError.h"
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
@@ -421,6 +424,21 @@ cl::list<std::string> InputFilename(cl::Positional,
 
 static ExitOnError ExitOnErr;
 
+static uint32_t
+getFileChecksumOffset(StringRef FileName,
+                      ModuleDebugFileChecksumFragment &Checksums,
+                      StringTableBuilder &Strings) {
+  // The offset in the line info record is the offset of the checksum
+  // entry for the corresponding file.  That entry then contains an
+  // offset into the global string table of the file name.  So to
+  // compute the proper offset to write into the line info record, we
+  // must first get its offset in the global string table, then ask the
+  // checksum builder to find the offset in its serialized buffer that
+  // it mapped that filename string table offset to.
+  uint32_t StringOffset = Strings.insert(FileName);
+  return Checksums.mapChecksumOffset(StringOffset);
+}
+
 static void yamlToPdb(StringRef Path) {
   BumpPtrAllocator Allocator;
   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
@@ -503,12 +521,19 @@ static void yamlToPdb(StringRef Path) {
       if (!FLI.FileChecksums.empty()) {
         auto &Strings = Builder.getStringTableBuilder();
         for (auto &FC : FLI.FileChecksums) {
-          uint32_t STOffset = Strings.getStringIndex(FC.FileName);
+          uint32_t STOffset = Strings.insert(FC.FileName);
           Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
         }
       }
       ModiBuilder.setC13FileChecksums(std::move(Checksums));
 
+      // FIXME: StringTable / StringTableBuilder should really be in
+      // DebugInfoCodeView.  This would allow us to construct the
+      // ModuleDebugLineFragment with a reference to the string table,
+      // and we could just pass strings around rather than having to
+      // remember how to calculate the right offset.
+      auto &Strings = Builder.getStringTableBuilder();
+
       for (const auto &Fragment : FLI.LineFragments) {
         auto Lines = llvm::make_unique<ModuleDebugLineFragment>();
         Lines->setCodeSize(Fragment.CodeSize);
@@ -516,21 +541,8 @@ static void yamlToPdb(StringRef Path) {
                                     Fragment.RelocOffset);
         Lines->setFlags(Fragment.Flags);
         for (const auto &LC : Fragment.Blocks) {
-          // FIXME: StringTable / StringTableBuilder should really be in
-          // DebugInfoCodeView.  This would allow us to construct the
-          // ModuleDebugLineFragment with a reference to the string table,
-          // and we could just pass strings around rather than having to
-          // remember how to calculate the right offset.
-          auto &Strings = Builder.getStringTableBuilder();
-          // The offset in the line info record is the offset of the checksum
-          // entry for the corresponding file.  That entry then contains an
-          // offset into the global string table of the file name.  So to
-          // compute the proper offset to write into the line info record, we
-          // must first get its offset in the global string table, then ask the
-          // checksum builder to find the offset in its serialized buffer that
-          // it mapped that filename string table offset to.
-          uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
-          uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
+          uint32_t ChecksumOffset =
+              getFileChecksumOffset(LC.FileName, ChecksumRef, Strings);
 
           Lines->createBlock(ChecksumOffset);
           if (Lines->hasColumnInfo()) {
@@ -550,7 +562,26 @@ static void yamlToPdb(StringRef Path) {
             }
           }
         }
-        ModiBuilder.addC13LineFragment(std::move(Lines));
+        ModiBuilder.addC13Fragment(std::move(Lines));
+      }
+
+      for (const auto &Inlinee : FLI.Inlinees) {
+        auto Inlinees = llvm::make_unique<ModuleDebugInlineeLineFragment>(
+            Inlinee.HasExtraFiles);
+        for (const auto &Site : Inlinee.Sites) {
+          uint32_t FileOff =
+              getFileChecksumOffset(Site.FileName, ChecksumRef, Strings);
+
+          Inlinees->addInlineSite(Site.Inlinee, FileOff, Site.SourceLineNum);
+          if (!Inlinee.HasExtraFiles)
+            continue;
+
+          for (auto EF : Site.ExtraFiles) {
+            FileOff = getFileChecksumOffset(EF, ChecksumRef, Strings);
+            Inlinees->addExtraFile(FileOff);
+          }
+        }
+        ModiBuilder.addC13Fragment(std::move(Inlinees));
       }
     }
   }
index abe0e8d6965d47a12ecbffe3367830de8cf61b9b..a7088c1c7419a222ceee7704e1dc09f5138f89cb 100644 (file)
@@ -26,6 +26,7 @@
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@@ -986,27 +987,20 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
 void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
   BinaryByteStream S(Subsection, llvm::support::little);
   BinaryStreamReader SR(S);
-  uint32_t Signature;
-  error(SR.readInteger(Signature));
-  bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
+  ModuleDebugInlineeLineFragmentRef Lines;
+  error(Lines.initialize(SR));
 
-  while (!SR.empty()) {
-    const InlineeSourceLine *ISL;
-    error(SR.readObject(ISL));
+  for (auto &Line : Lines) {
     DictScope S(W, "InlineeSourceLine");
-    printTypeIndex("Inlinee", ISL->Inlinee);
-    printFileNameForOffset("FileID", ISL->FileID);
-    W.printNumber("SourceLineNum", ISL->SourceLineNum);
-
-    if (HasExtraFiles) {
-      uint32_t ExtraFileCount;
-      error(SR.readInteger(ExtraFileCount));
-      W.printNumber("ExtraFileCount", ExtraFileCount);
+    printTypeIndex("Inlinee", Line.Header->Inlinee);
+    printFileNameForOffset("FileID", Line.Header->FileID);
+    W.printNumber("SourceLineNum", Line.Header->SourceLineNum);
+
+    if (Lines.hasExtraFiles()) {
+      W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
       ListScope ExtraFiles(W, "ExtraFiles");
-      for (unsigned I = 0; I < ExtraFileCount; ++I) {
-        uint32_t FileID;
-        error(SR.readInteger(FileID));
-        printFileNameForOffset("FileID", FileID);
+      for (const auto &FID : Line.ExtraFiles) {
+        printFileNameForOffset("FileID", FID);
       }
     }
   }