[pdb] Write the IPI stream.
authorZachary Turner <zturner@google.com>
Thu, 15 Sep 2016 18:22:31 +0000 (18:22 +0000)
committerZachary Turner <zturner@google.com>
Thu, 15 Sep 2016 18:22:31 +0000 (18:22 +0000)
The IPI stream is structurally identical to the TPI stream, but it
contains different record types.  So we just re-use the TPI writing
code.

llvm-svn: 281638

llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
llvm/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h
llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
llvm/tools/llvm-pdbdump/PdbYaml.cpp
llvm/tools/llvm-pdbdump/PdbYaml.h
llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
llvm/tools/llvm-pdbdump/llvm-pdbdump.h

index 2107430..52170a4 100644 (file)
@@ -42,6 +42,7 @@ public:
   InfoStreamBuilder &getInfoBuilder();
   DbiStreamBuilder &getDbiBuilder();
   TpiStreamBuilder &getTpiBuilder();
+  TpiStreamBuilder &getIpiBuilder();
 
   Expected<std::unique_ptr<PDBFile>>
   build(std::unique_ptr<msf::WritableStream> PdbFileBuffer);
@@ -57,6 +58,7 @@ private:
   std::unique_ptr<InfoStreamBuilder> Info;
   std::unique_ptr<DbiStreamBuilder> Dbi;
   std::unique_ptr<TpiStreamBuilder> Tpi;
+  std::unique_ptr<TpiStreamBuilder> Ipi;
 };
 }
 }
index 7329bf8..2248fc8 100644 (file)
@@ -45,7 +45,7 @@ struct TpiStreamHeader;
 
 class TpiStreamBuilder {
 public:
-  explicit TpiStreamBuilder(msf::MSFBuilder &Msf);
+  explicit TpiStreamBuilder(msf::MSFBuilder &Msf, uint32_t StreamIdx);
   ~TpiStreamBuilder();
 
   TpiStreamBuilder(const TpiStreamBuilder &) = delete;
@@ -77,6 +77,7 @@ private:
   std::unique_ptr<msf::ByteStream> HashValueStream;
 
   const TpiStreamHeader *Header;
+  uint32_t Idx;
 };
 }
 }
index 40e3c79..165b03c 100644 (file)
@@ -62,10 +62,16 @@ DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
 
 TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
   if (!Tpi)
-    Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf);
+    Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
   return *Tpi;
 }
 
+TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
+  if (!Ipi)
+    Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
+  return *Ipi;
+}
+
 Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
   if (Info) {
     if (auto EC = Info->finalizeMsfLayout())
@@ -79,6 +85,10 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
     if (auto EC = Tpi->finalizeMsfLayout())
       return std::move(EC);
   }
+  if (Ipi) {
+    if (auto EC = Ipi->finalizeMsfLayout())
+      return std::move(EC);
+  }
 
   return Msf->build();
 }
@@ -113,6 +123,13 @@ PDBFileBuilder::build(std::unique_ptr<msf::WritableStream> PdbFileBuffer) {
     File->Tpi = std::move(*ExpectedTpi);
   }
 
+  if (Ipi) {
+    auto ExpectedIpi = Ipi->build(*File, *PdbFileBuffer);
+    if (!ExpectedIpi)
+      return ExpectedIpi.takeError();
+    File->Ipi = std::move(*ExpectedIpi);
+  }
+
   if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
     return llvm::make_error<RawError>(
         raw_error_code::corrupt_file,
@@ -166,5 +183,10 @@ Error PDBFileBuilder::commit(const msf::WritableStream &Buffer) {
       return EC;
   }
 
+  if (Ipi) {
+    if (auto EC = Ipi->commit(Layout, Buffer))
+      return EC;
+  }
+
   return Buffer.commit();
 }
\ No newline at end of file
index aa05938..733efe8 100644 (file)
@@ -15,8 +15,9 @@ using namespace llvm::msf;
 using namespace llvm::pdb;
 using namespace llvm::support;
 
-TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf)
-    : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr) {}
+TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
+    : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
+}
 
 TpiStreamBuilder::~TpiStreamBuilder() {}
 
@@ -75,7 +76,7 @@ uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
 
 Error TpiStreamBuilder::finalizeMsfLayout() {
   uint32_t Length = calculateSerializedLength();
-  if (auto EC = Msf.setStreamSize(StreamTPI, Length))
+  if (auto EC = Msf.setStreamSize(Idx, Length))
     return EC;
 
   uint32_t HashBufferSize = calculateHashBufferSize();
@@ -106,8 +107,8 @@ TpiStreamBuilder::build(PDBFile &File, const msf::WritableStream &Buffer) {
   if (auto EC = finalize())
     return std::move(EC);
 
-  auto StreamData = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
-                                                           Buffer, StreamTPI);
+  auto StreamData =
+      MappedBlockStream::createIndexedStream(File.getMsfLayout(), Buffer, Idx);
   auto Tpi = llvm::make_unique<TpiStream>(File, std::move(StreamData));
   Tpi->Header = Header;
   Tpi->TypeRecords = VarStreamArray<codeview::CVType>(TypeRecordStream);
@@ -126,7 +127,7 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
     return EC;
 
   auto InfoS =
-      WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamTPI);
+      WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
 
   StreamWriter Writer(*InfoS);
   if (auto EC = Writer.writeObject(*Header))
index 3975bdf..fd1016b 100644 (file)
@@ -138,6 +138,7 @@ void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
   IO.mapOptional("PdbStream", Obj.PdbStream);
   IO.mapOptional("DbiStream", Obj.DbiStream);
   IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
+  IO.mapOptionalWithContext("IpiStream", Obj.IpiStream, Obj.Allocator);
 }
 
 void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
index 7ae1861..ffa194d 100644 (file)
@@ -93,6 +93,7 @@ struct PdbObject {
   Optional<PdbInfoStream> PdbStream;
   Optional<PdbDbiStream> DbiStream;
   Optional<PdbTpiStream> TpiStream;
+  Optional<PdbTpiStream> IpiStream;
 
   BumpPtrAllocator &Allocator;
 };
index 0991d5c..ee1875c 100644 (file)
@@ -50,6 +50,9 @@ Error YAMLOutputStyle::dump() {
   if (auto EC = dumpTpiStream())
     return EC;
 
+  if (auto EC = dumpIpiStream())
+    return EC;
+
   flush();
   return Error::success();
 }
@@ -179,6 +182,26 @@ Error YAMLOutputStyle::dumpTpiStream() {
   return Error::success();
 }
 
+Error YAMLOutputStyle::dumpIpiStream() {
+  if (!opts::pdb2yaml::IpiStream)
+    return Error::success();
+
+  auto IpiS = File.getPDBIpiStream();
+  if (!IpiS)
+    return IpiS.takeError();
+
+  auto &IS = IpiS.get();
+  Obj.IpiStream.emplace();
+  Obj.IpiStream->Version = IS.getTpiVersion();
+  for (auto &Record : IS.types(nullptr)) {
+    yaml::PdbTpiRecord R;
+    R.Record = Record;
+    Obj.IpiStream->Records.push_back(R);
+  }
+
+  return Error::success();
+}
+
 void YAMLOutputStyle::flush() {
   Out << Obj;
   outs().flush();
index 3204bdd..540dee4 100644 (file)
@@ -32,6 +32,7 @@ private:
   Error dumpPDBStream();
   Error dumpDbiStream();
   Error dumpTpiStream();
+  Error dumpIpiStream();
 
   void flush();
 
index d1858f0..ca46660 100644 (file)
@@ -290,6 +290,10 @@ cl::opt<bool> TpiStream("tpi-stream",
                         cl::desc("Dump the TPI Stream (Stream 3)"),
                         cl::sub(PdbToYamlSubcommand), cl::init(false));
 
+cl::opt<bool> IpiStream("ipi-stream",
+                        cl::desc("Dump the IPI Stream (Stream 5)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+
 cl::list<std::string> InputFilename(cl::Positional,
                                     cl::desc("<input PDB file>"), cl::Required,
                                     cl::sub(PdbToYamlSubcommand));
@@ -371,6 +375,13 @@ static void yamlToPdb(StringRef Path) {
       TpiBuilder.addTypeRecord(R.Record);
   }
 
+  if (YamlObj.IpiStream.hasValue()) {
+    auto &IpiBuilder = Builder.getIpiBuilder();
+    IpiBuilder.setVersionHeader(YamlObj.IpiStream->Version);
+    for (const auto &R : YamlObj.IpiStream->Records)
+      IpiBuilder.addTypeRecord(R.Record);
+  }
+
   ExitOnErr(Builder.commit(*FileByteStream));
 }
 
index 74ce077..8f05ca7 100644 (file)
@@ -73,6 +73,7 @@ extern llvm::cl::opt<bool> DbiStream;
 extern llvm::cl::opt<bool> DbiModuleInfo;
 extern llvm::cl::opt<bool> DbiModuleSourceFileInfo;
 extern llvm::cl::opt<bool> TpiStream;
+extern llvm::cl::opt<bool> IpiStream;
 extern llvm::cl::list<std::string> InputFilename;
 }
 }