[llvm] r275627 - [pdb] Use MsfBuilder to handle the writing PDBs.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 15 15:16:56 PDT 2016


Author: zturner
Date: Fri Jul 15 17:16:56 2016
New Revision: 275627

URL: http://llvm.org/viewvc/llvm-project?rev=275627&view=rev
Log:
[pdb] Use MsfBuilder to handle the writing PDBs.

Previously we would read a PDB, then write some of it back out,
but write the directory, super block, and other pertinent metadata
back out unchanged.  This generates incorrect PDBs since the amount
of data written was not always the same as the amount of data read.

This patch changes things to use the newly introduced `MsfBuilder`
class to write out a correct and accurate set of Msf metadata for
the data *actually* written, which opens up the door for adding and
removing type records, symbol records, and other types of data to
an existing PDB.

Added:
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
    llvm/trunk/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
    llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStream.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStream.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
    llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp
    llvm/trunk/tools/llvm-pdbdump/PdbYaml.h
    llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
    llvm/trunk/unittests/DebugInfo/PDB/MsfBuilderTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h Fri Jul 15 17:16:56 2016
@@ -112,10 +112,14 @@ public:
   VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
                          bool *HadError = nullptr)
       : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
-    auto EC = Extract(IterRef, ThisLen, ThisValue);
-    if (EC) {
-      consumeError(std::move(EC));
-      markError();
+    if (IterRef.getLength() == 0)
+      moveToEnd();
+    else {
+      auto EC = Extract(IterRef, ThisLen, ThisValue);
+      if (EC) {
+        consumeError(std::move(EC));
+        markError();
+      }
     }
   }
   VarStreamArrayIterator() {}

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h Fri Jul 15 17:16:56 2016
@@ -24,7 +24,7 @@ class PDBFile;
 
 class DbiStreamBuilder {
 public:
-  DbiStreamBuilder(PDBFile &File);
+  DbiStreamBuilder();
 
   DbiStreamBuilder(const DbiStreamBuilder &) = delete;
   DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
@@ -37,10 +37,11 @@ public:
   void setFlags(uint16_t F);
   void setMachineType(PDB_Machine M);
 
-  Expected<std::unique_ptr<DbiStream>> build();
+  uint32_t calculateSerializedLength() const;
+
+  Expected<std::unique_ptr<DbiStream>> build(PDBFile &File);
 
 private:
-  PDBFile &File;
   Optional<PdbRaw_DbiVer> VerHeader;
   uint32_t Age;
   uint16_t BuildNumber;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStream.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStream.h Fri Jul 15 17:16:56 2016
@@ -27,7 +27,7 @@ class PDBFile;
 class InfoStream {
   friend class InfoStreamBuilder;
 
-  struct Header {
+  struct HeaderInfo {
     support::ulittle32_t Version;
     support::ulittle32_t Signature;
     support::ulittle32_t Age;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h Fri Jul 15 17:16:56 2016
@@ -14,18 +14,17 @@
 #include "llvm/Support/Error.h"
 
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
+#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
 
 namespace llvm {
 namespace pdb {
-class NameMap;
 class PDBFile;
 
 class InfoStreamBuilder {
 public:
-  InfoStreamBuilder(IPDBFile &File);
+  InfoStreamBuilder();
   InfoStreamBuilder(const InfoStreamBuilder &) = delete;
   InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
 
@@ -34,15 +33,17 @@ public:
   void setAge(uint32_t A);
   void setGuid(PDB_UniqueId G);
 
-  Expected<std::unique_ptr<InfoStream>> build();
+  uint32_t calculateSerializedLength() const;
+
+  Expected<std::unique_ptr<InfoStream>> build(PDBFile &File);
 
 private:
-  IPDBFile &File;
   Optional<PdbRaw_ImplVer> Ver;
   Optional<uint32_t> Sig;
   Optional<uint32_t> Age;
   Optional<PDB_UniqueId> Guid;
-  Optional<NameMap> NamedStreams;
+
+  NameMapBuilder NamedStreams;
 };
 }
 }

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h Fri Jul 15 17:16:56 2016
@@ -63,6 +63,9 @@ public:
   /// Request the block map to be at a specific block address.  This is useful
   /// when editing a PDB and you want the layout to be as stable as possible.
   Error setBlockMapAddr(uint32_t Addr);
+  Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks);
+  void setUnknown0(uint32_t Unk0);
+  void setUnknown1(uint32_t Unk1);
 
   /// Add a stream to the MSF file with the given size, occupying the given
   /// list of blocks.  This is useful when reading a PDB file and you want a
@@ -123,6 +126,8 @@ private:
   BumpPtrAllocator &Allocator;
 
   bool IsGrowable;
+  uint32_t Unknown0;
+  uint32_t Unknown1;
   uint32_t BlockSize;
   uint32_t MininumBlocks;
   uint32_t BlockMapAddr;

Added: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h?rev=275627&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h Fri Jul 15 17:16:56 2016
@@ -0,0 +1,34 @@
+//===- NameMapBuilder.h - PDB Name Map Builder ------------------*- 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_PDB_RAW_PDBNAMEMAPBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
+
+#include "llvm/Support/Error.h"
+
+#include <cstdint>
+#include <memory>
+
+namespace llvm {
+namespace pdb {
+class NameMap;
+
+class NameMapBuilder {
+public:
+  NameMapBuilder();
+
+  Expected<std::unique_ptr<NameMap>> build();
+
+  uint32_t calculateSerializedLength() const;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h Fri Jul 15 17:16:56 2016
@@ -14,6 +14,7 @@
 #include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/StreamInterface.h"
 #include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
@@ -37,38 +38,10 @@ class PublicsStream;
 class SymbolStream;
 class TpiStream;
 
-static const char MsfMagic[] = {'M',  'i',  'c',    'r', 'o', 's',  'o',  'f',
-                                't',  ' ',  'C',    '/', 'C', '+',  '+',  ' ',
-                                'M',  'S',  'F',    ' ', '7', '.',  '0',  '0',
-                                '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'};
-
 class PDBFile : public IPDBFile {
   friend PDBFileBuilder;
 
 public:
-  // The superblock is overlaid at the beginning of the file (offset 0).
-  // It starts with a magic header and is followed by information which
-  // describes the layout of the file system.
-  struct SuperBlock {
-    char MagicBytes[sizeof(MsfMagic)];
-    // The file system is split into a variable number of fixed size elements.
-    // These elements are referred to as blocks.  The size of a block may vary
-    // from system to system.
-    support::ulittle32_t BlockSize;
-    // This field's purpose is not yet known.
-    support::ulittle32_t Unknown0;
-    // This contains the number of blocks resident in the file system.  In
-    // practice, NumBlocks * BlockSize is equivalent to the size of the PDB
-    // file.
-    support::ulittle32_t NumBlocks;
-    // This contains the number of bytes which make up the directory.
-    support::ulittle32_t NumDirectoryBytes;
-    // This field's purpose is not yet known.
-    support::ulittle32_t Unknown1;
-    // This contains the block # of the block map.
-    support::ulittle32_t BlockMapAddr;
-  };
-
   explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
   ~PDBFile() override;
 
@@ -103,14 +76,6 @@ public:
   Error parseFileHeaders();
   Error parseStreamData();
 
-  static uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) {
-    return alignTo(NumBytes, BlockSize) / BlockSize;
-  }
-
-  static uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) {
-    return BlockNumber * BlockSize;
-  }
-
   Expected<InfoStream &> getPDBInfoStream();
   Expected<DbiStream &> getPDBDbiStream();
   Expected<TpiStream &> getPDBTpiStream();
@@ -122,12 +87,12 @@ public:
   Error commit();
 
 private:
-  Error setSuperBlock(const SuperBlock *Block);
+  Error setSuperBlock(const msf::SuperBlock *Block);
 
   BumpPtrAllocator Allocator;
 
   std::unique_ptr<codeview::StreamInterface> Buffer;
-  const PDBFile::SuperBlock *SB;
+  const msf::SuperBlock *SB;
   ArrayRef<support::ulittle32_t> StreamSizes;
   ArrayRef<support::ulittle32_t> DirectoryBlocks;
   std::vector<ArrayRef<support::ulittle32_t>> StreamMap;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h Fri Jul 15 17:16:56 2016
@@ -11,10 +11,12 @@
 #define LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 
+#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h"
 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
 
 #include <memory>
@@ -32,27 +34,24 @@ class PDBFile;
 class PDBFileBuilder {
 public:
   explicit PDBFileBuilder(
-      std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
+      std::unique_ptr<codeview::StreamInterface> FileBuffer);
   PDBFileBuilder(const PDBFileBuilder &) = delete;
   PDBFileBuilder &operator=(const PDBFileBuilder &) = delete;
 
-  Error setSuperBlock(const PDBFile::SuperBlock &B);
-  void setStreamSizes(ArrayRef<support::ulittle32_t> S);
-  void setDirectoryBlocks(ArrayRef<support::ulittle32_t> D);
-  void setStreamMap(const std::vector<ArrayRef<support::ulittle32_t>> &S);
-  Error generateSimpleStreamMap();
+  Error initialize(const msf::SuperBlock &Super);
 
+  MsfBuilder &getMsfBuilder();
   InfoStreamBuilder &getInfoBuilder();
   DbiStreamBuilder &getDbiBuilder();
 
   Expected<std::unique_ptr<PDBFile>> build();
 
 private:
-  std::unique_ptr<codeview::StreamInterface> PdbFileBuffer;
   std::unique_ptr<InfoStreamBuilder> Info;
   std::unique_ptr<DbiStreamBuilder> Dbi;
 
   std::unique_ptr<PDBFile> File;
+  std::unique_ptr<MsfBuilder> Msf;
 };
 }
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt Fri Jul 15 17:16:56 2016
@@ -42,6 +42,7 @@ add_pdb_impl_folder(Raw
   Raw/MsfCommon.cpp
   Raw/NameHashTable.cpp
   Raw/NameMap.cpp
+  Raw/NameMapBuilder.cpp
   Raw/PDBFile.cpp
   Raw/PDBFileBuilder.cpp
   Raw/PublicsStream.cpp

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStream.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStream.cpp Fri Jul 15 17:16:56 2016
@@ -182,9 +182,11 @@ Error DbiStream::reload() {
     return make_error<RawError>(raw_error_code::corrupt_file,
                                 "Found unexpected bytes in DBI Stream.");
 
-  StreamReader ECReader(ECSubstream);
-  if (auto EC = ECNames.load(ECReader))
-    return EC;
+  if (ECSubstream.getLength() > 0) {
+    StreamReader ECReader(ECSubstream);
+    if (auto EC = ECNames.load(ECReader))
+      return EC;
+  }
 
   return Error::success();
 }
@@ -267,6 +269,9 @@ void llvm::pdb::DbiStream::visitSectionC
 }
 
 Error DbiStream::initializeSectionContributionData() {
+  if (SecContrSubstream.getLength() == 0)
+    return Error::success();
+
   StreamReader SCReader(SecContrSubstream);
   if (auto EC = SCReader.readEnum(SectionContribVersion))
     return EC;
@@ -282,6 +287,9 @@ Error DbiStream::initializeSectionContri
 
 // Initializes this->SectionHeaders.
 Error DbiStream::initializeSectionHeadersData() {
+  if (DbgStreams.size() == 0)
+    return Error::success();
+
   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
   if (StreamNum >= Pdb.getNumStreams())
     return make_error<RawError>(raw_error_code::no_stream);
@@ -307,6 +315,9 @@ Error DbiStream::initializeSectionHeader
 
 // Initializes this->Fpos.
 Error DbiStream::initializeFpoRecords() {
+  if (DbgStreams.size() == 0)
+    return Error::success();
+
   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
 
   // This means there is no FPO data.
@@ -335,6 +346,9 @@ Error DbiStream::initializeFpoRecords()
 }
 
 Error DbiStream::initializeSectionMapData() {
+  if (SecMapSubstream.getLength() == 0)
+    return Error::success();
+
   StreamReader SMReader(SecMapSubstream);
   const SecMapHeader *Header;
   if (auto EC = SMReader.readObject(Header))
@@ -357,6 +371,9 @@ Error DbiStream::initializeFileInfo() {
   // with the caveat that `NumSourceFiles` cannot be trusted, so
   // it is computed by summing `ModFileCounts`.
   //
+  if (FileInfoSubstream.getLength() == 0)
+    return Error::success();
+
   const FileInfoSubstreamHeader *FH;
   StreamReader FISR(FileInfoSubstream);
   if (auto EC = FISR.readObject(FH))
@@ -436,4 +453,10 @@ Expected<StringRef> DbiStream::getFileNa
   return Name;
 }
 
-Error DbiStream::commit() { return Error::success(); }
+Error DbiStream::commit() {
+  StreamWriter Writer(*Stream);
+  if (auto EC = Writer.writeObject(*Header))
+    return EC;
+
+  return Error::success();
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp Fri Jul 15 17:16:56 2016
@@ -18,9 +18,9 @@ using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
-DbiStreamBuilder::DbiStreamBuilder(PDBFile &File)
-    : File(File), Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0),
-      Flags(0), MachineType(PDB_Machine::x86) {}
+DbiStreamBuilder::DbiStreamBuilder()
+    : Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0),
+      MachineType(PDB_Machine::x86) {}
 
 void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
 
@@ -36,7 +36,12 @@ void DbiStreamBuilder::setFlags(uint16_t
 
 void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
 
-Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build() {
+uint32_t DbiStreamBuilder::calculateSerializedLength() const {
+  // For now we only support serializing the header.
+  return sizeof(DbiStream::HeaderInfo);
+}
+
+Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
   if (!VerHeader.hasValue())
     return make_error<RawError>(raw_error_code::unspecified,
                                 "Missing DBI Stream Version");

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStream.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStream.cpp Fri Jul 15 17:16:56 2016
@@ -27,7 +27,7 @@ InfoStream::InfoStream(std::unique_ptr<M
 Error InfoStream::reload() {
   codeview::StreamReader Reader(*Stream);
 
-  const Header *H;
+  const HeaderInfo *H;
   if (auto EC = Reader.readObject(H))
     return joinErrors(
         std::move(EC),
@@ -78,7 +78,7 @@ PDB_UniqueId InfoStream::getGuid() const
 Error InfoStream::commit() {
   StreamWriter Writer(*Stream);
 
-  Header H;
+  HeaderInfo H;
   H.Age = Age;
   H.Signature = Signature;
   H.Version = Version;
@@ -87,4 +87,4 @@ Error InfoStream::commit() {
     return EC;
 
   return NamedStreams.commit(Writer);
-}
\ No newline at end of file
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp Fri Jul 15 17:16:56 2016
@@ -18,7 +18,7 @@ using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
-InfoStreamBuilder::InfoStreamBuilder(IPDBFile &File) : File(File) {}
+InfoStreamBuilder::InfoStreamBuilder() {}
 
 void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
 
@@ -28,7 +28,12 @@ void InfoStreamBuilder::setAge(uint32_t
 
 void InfoStreamBuilder::setGuid(PDB_UniqueId G) { Guid = G; }
 
-Expected<std::unique_ptr<InfoStream>> InfoStreamBuilder::build() {
+uint32_t InfoStreamBuilder::calculateSerializedLength() const {
+  return sizeof(InfoStream::HeaderInfo) +
+         NamedStreams.calculateSerializedLength();
+}
+
+Expected<std::unique_ptr<InfoStream>> InfoStreamBuilder::build(PDBFile &File) {
   if (!Ver.hasValue())
     return make_error<RawError>(raw_error_code::unspecified,
                                 "Missing PDB Stream Version");

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp Fri Jul 15 17:16:56 2016
@@ -24,7 +24,7 @@ MsfBuilder::MsfBuilder(uint32_t BlockSiz
                        BumpPtrAllocator &Allocator)
     : Allocator(Allocator), IsGrowable(CanGrow), BlockSize(BlockSize),
       MininumBlocks(MinBlockCount), BlockMapAddr(kDefaultBlockMapAddr),
-      FreeBlocks(MinBlockCount + 2U, true) {
+      FreeBlocks(std::max(MinBlockCount, 2U), true) {
   FreeBlocks[kSuperBlockBlock] = false;
   FreeBlocks[BlockMapAddr] = false;
 }
@@ -59,6 +59,25 @@ Error MsfBuilder::setBlockMapAddr(uint32
   return Error::success();
 }
 
+void MsfBuilder::setUnknown0(uint32_t Unk0) { Unknown0 = Unk0; }
+
+void MsfBuilder::setUnknown1(uint32_t Unk1) { Unknown1 = Unk1; }
+
+Error MsfBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
+  for (auto B : DirectoryBlocks)
+    FreeBlocks[B] = true;
+  for (auto B : DirBlocks) {
+    if (!isBlockFree(B)) {
+      return make_error<RawError>(raw_error_code::unspecified,
+                                  "Attempt to reuse an allocated block");
+    }
+    FreeBlocks[B] = false;
+  }
+
+  DirectoryBlocks = DirBlocks;
+  return Error::success();
+}
+
 Error MsfBuilder::allocateBlocks(uint32_t NumBlocks,
                                  MutableArrayRef<uint32_t> Blocks) {
   if (NumBlocks == 0)
@@ -198,16 +217,28 @@ Expected<Layout> MsfBuilder::build() {
   L.SB->BlockMapAddr = BlockMapAddr;
   L.SB->BlockSize = BlockSize;
   L.SB->NumDirectoryBytes = computeDirectoryByteSize();
-  L.SB->Unknown0 = 0;
-  L.SB->Unknown1 = 0;
+  L.SB->Unknown0 = Unknown0;
+  L.SB->Unknown1 = Unknown1;
 
   uint32_t NumDirectoryBlocks =
       bytesToBlocks(L.SB->NumDirectoryBytes, BlockSize);
-  // The directory blocks should be re-allocated as a stable pointer.
-  std::vector<uint32_t> DirectoryBlocks;
-  DirectoryBlocks.resize(NumDirectoryBlocks);
-  if (auto EC = allocateBlocks(NumDirectoryBlocks, DirectoryBlocks))
-    return std::move(EC);
+  if (NumDirectoryBlocks > DirectoryBlocks.size()) {
+    // Our hint wasn't enough to satisfy the entire directory.  Allocate
+    // remaining pages.
+    std::vector<uint32_t> ExtraBlocks;
+    uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
+    ExtraBlocks.resize(NumExtraBlocks);
+    if (auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
+      return std::move(EC);
+    DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(),
+                           ExtraBlocks.end());
+  } else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
+    uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
+    for (auto B :
+         ArrayRef<uint32_t>(DirectoryBlocks).drop_back(NumUnnecessaryBlocks))
+      FreeBlocks[B] = true;
+    DirectoryBlocks.resize(NumDirectoryBlocks);
+  }
 
   // Don't set the number of blocks in the file until after allocating Blocks
   // for

Added: llvm/trunk/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp?rev=275627&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp (added)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp Fri Jul 15 17:16:56 2016
@@ -0,0 +1,26 @@
+//===- NameMapBuilder.cpp - PDB Name Map Builder ----------------*- 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/PDB/Raw/NameMapBuilder.h"
+
+#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NameMapBuilder::NameMapBuilder() {}
+
+Expected<std::unique_ptr<NameMap>> NameMapBuilder::build() {
+  return llvm::make_unique<NameMap>();
+}
+
+uint32_t NameMapBuilder::calculateSerializedLength() const {
+  // For now we write an empty name map, nothing else.
+  return 5 * sizeof(uint32_t);
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp Fri Jul 15 17:16:56 2016
@@ -53,7 +53,7 @@ uint32_t PDBFile::getBlockMapIndex() con
 uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
 
 uint32_t PDBFile::getNumDirectoryBlocks() const {
-  return bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
+  return msf::bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
 }
 
 uint64_t PDBFile::getBlockMapOffset() const {
@@ -75,7 +75,7 @@ uint32_t PDBFile::getFileSize() const {
 
 Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
                                                   uint32_t NumBytes) const {
-  uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
+  uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
 
   ArrayRef<uint8_t> Result;
   if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
@@ -94,7 +94,7 @@ Error PDBFile::setBlockData(uint32_t Blo
         raw_error_code::invalid_block_address,
         "setBlockData attempted to write out of block bounds.");
 
-  uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
+  uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
   StreamBlockOffset += Offset;
   return Buffer->writeBytes(StreamBlockOffset, Data);
 }
@@ -143,7 +143,8 @@ Error PDBFile::parseStreamData() {
     uint32_t StreamSize = getStreamByteSize(I);
     // FIXME: What does StreamSize ~0U mean?
     uint64_t NumExpectedStreamBlocks =
-        StreamSize == UINT32_MAX ? 0 : bytesToBlocks(StreamSize, SB->BlockSize);
+        StreamSize == UINT32_MAX ? 0 : msf::bytesToBlocks(StreamSize,
+                                                          SB->BlockSize);
 
     // For convenience, we store the block array contiguously.  This is because
     // if someone calls setStreamMap(), it is more convenient to be able to call
@@ -293,51 +294,15 @@ Expected<NameHashTable &> PDBFile::getSt
   return *StringTable;
 }
 
-Error PDBFile::setSuperBlock(const SuperBlock *Block) {
-  SB = Block;
-
-  // Check the magic bytes.
-  if (memcmp(SB->MagicBytes, MsfMagic, sizeof(MsfMagic)) != 0)
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "MSF magic header doesn't match");
-
-  // We don't support blocksizes which aren't a multiple of four bytes.
-  if (SB->BlockSize % sizeof(support::ulittle32_t) != 0)
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "Block size is not multiple of 4.");
-
-  switch (SB->BlockSize) {
-  case 512:
-  case 1024:
-  case 2048:
-  case 4096:
-    break;
-  default:
-    // An invalid block size suggests a corrupt PDB file.
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "Unsupported block size.");
-  }
+Error PDBFile::setSuperBlock(const msf::SuperBlock *Block) {
+  if (auto EC = msf::validateSuperBlock(*Block))
+    return EC;
 
   if (Buffer->getLength() % SB->BlockSize != 0)
     return make_error<RawError>(raw_error_code::corrupt_file,
                                 "File size is not a multiple of block size");
 
-  // We don't support directories whose sizes aren't a multiple of four bytes.
-  if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "Directory size is not multiple of 4.");
-
-  // The number of blocks which comprise the directory is a simple function of
-  // the number of bytes it contains.
-  uint64_t NumDirectoryBlocks = getNumDirectoryBlocks();
-
-  // The directory, as we understand it, is a block which consists of a list of
-  // block numbers.  It is unclear what would happen if the number of blocks
-  // couldn't fit on a single block.
-  if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t))
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "Too many directory blocks.");
-
+  SB = Block;
   return Error::success();
 }
 

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp Fri Jul 15 17:16:56 2016
@@ -9,6 +9,8 @@
 
 #include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
 
+#include "llvm/ADT/BitVector.h"
+
 #include "llvm/DebugInfo/CodeView/StreamInterface.h"
 #include "llvm/DebugInfo/CodeView/StreamWriter.h"
 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
@@ -20,99 +22,72 @@
 using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
+using namespace llvm::support;
 
 PDBFileBuilder::PDBFileBuilder(
-    std::unique_ptr<codeview::StreamInterface> PdbFileBuffer)
-    : File(llvm::make_unique<PDBFile>(std::move(PdbFileBuffer))) {}
-
-Error PDBFileBuilder::setSuperBlock(const PDBFile::SuperBlock &B) {
-  auto SB = static_cast<PDBFile::SuperBlock *>(
-      File->Allocator.Allocate(sizeof(PDBFile::SuperBlock),
-                               llvm::AlignOf<PDBFile::SuperBlock>::Alignment));
-  ::memcpy(SB, &B, sizeof(PDBFile::SuperBlock));
-  return File->setSuperBlock(SB);
-}
-
-void PDBFileBuilder::setStreamSizes(ArrayRef<support::ulittle32_t> S) {
-  File->StreamSizes = S;
-}
-
-void PDBFileBuilder::setDirectoryBlocks(ArrayRef<support::ulittle32_t> D) {
-  File->DirectoryBlocks = D;
-}
-
-void PDBFileBuilder::setStreamMap(
-    const std::vector<ArrayRef<support::ulittle32_t>> &S) {
-  File->StreamMap = S;
-}
+    std::unique_ptr<codeview::StreamInterface> FileBuffer)
+    : File(llvm::make_unique<PDBFile>(std::move(FileBuffer))) {}
 
-Error PDBFileBuilder::generateSimpleStreamMap() {
-  if (File->StreamSizes.empty())
-    return Error::success();
-
-  static std::vector<std::vector<support::ulittle32_t>> StaticMap;
-  File->StreamMap.clear();
-  StaticMap.clear();
-
-  // Figure out how many blocks are needed for all streams, and set the first
-  // used block to the highest block so that we can write the rest of the
-  // blocks contiguously.
-  uint32_t TotalFileBlocks = File->getBlockCount();
-  std::vector<support::ulittle32_t> ReservedBlocks;
-  ReservedBlocks.push_back(support::ulittle32_t(0));
-  ReservedBlocks.push_back(File->SB->BlockMapAddr);
-  ReservedBlocks.insert(ReservedBlocks.end(), File->DirectoryBlocks.begin(),
-                        File->DirectoryBlocks.end());
-
-  uint32_t BlocksNeeded = 0;
-  for (auto Size : File->StreamSizes)
-    BlocksNeeded += File->bytesToBlocks(Size, File->getBlockSize());
-
-  support::ulittle32_t NextBlock(TotalFileBlocks - BlocksNeeded -
-                                 ReservedBlocks.size());
-
-  StaticMap.resize(File->StreamSizes.size());
-  for (uint32_t S = 0; S < File->StreamSizes.size(); ++S) {
-    uint32_t Size = File->StreamSizes[S];
-    uint32_t NumBlocks = File->bytesToBlocks(Size, File->getBlockSize());
-    auto &ThisStream = StaticMap[S];
-    for (uint32_t I = 0; I < NumBlocks;) {
-      NextBlock += 1;
-      if (std::find(ReservedBlocks.begin(), ReservedBlocks.end(), NextBlock) !=
-          ReservedBlocks.end())
-        continue;
-
-      ++I;
-      assert(NextBlock < File->getBlockCount());
-      ThisStream.push_back(NextBlock);
-    }
-    File->StreamMap.push_back(ThisStream);
-  }
+Error PDBFileBuilder::initialize(const msf::SuperBlock &Super) {
+  auto ExpectedMsf =
+      MsfBuilder::create(File->Allocator, Super.BlockSize, Super.NumBlocks);
+  if (!ExpectedMsf)
+    return ExpectedMsf.takeError();
+
+  auto &MsfResult = *ExpectedMsf;
+  if (auto EC = MsfResult.setBlockMapAddr(Super.BlockMapAddr))
+    return EC;
+  MsfResult.setUnknown0(Super.Unknown0);
+  MsfResult.setUnknown1(Super.Unknown1);
+  Msf = llvm::make_unique<MsfBuilder>(std::move(MsfResult));
   return Error::success();
 }
 
+MsfBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
+
 InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
   if (!Info)
-    Info = llvm::make_unique<InfoStreamBuilder>(*File);
+    Info = llvm::make_unique<InfoStreamBuilder>();
   return *Info;
 }
 
 DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
   if (!Dbi)
-    Dbi = llvm::make_unique<DbiStreamBuilder>(*File);
+    Dbi = llvm::make_unique<DbiStreamBuilder>();
   return *Dbi;
 }
 
 Expected<std::unique_ptr<PDBFile>> PDBFileBuilder::build() {
   if (Info) {
-    auto ExpectedInfo = Info->build();
+    uint32_t Length = Info->calculateSerializedLength();
+    if (auto EC = Msf->setStreamSize(StreamPDB, Length))
+      return std::move(EC);
+  }
+  if (Dbi) {
+    uint32_t Length = Dbi->calculateSerializedLength();
+    if (auto EC = Msf->setStreamSize(StreamDBI, Length))
+      return std::move(EC);
+  }
+
+  auto ExpectedLayout = Msf->build();
+  if (!ExpectedLayout)
+    return ExpectedLayout.takeError();
+
+  const msf::Layout &L = *ExpectedLayout;
+  File->StreamMap = L.StreamMap;
+  File->StreamSizes = L.StreamSizes;
+  File->DirectoryBlocks = L.DirectoryBlocks;
+  File->SB = L.SB;
+
+  if (Info) {
+    auto ExpectedInfo = Info->build(*File);
     if (!ExpectedInfo)
       return ExpectedInfo.takeError();
     File->Info = std::move(*ExpectedInfo);
   }
 
   if (Dbi) {
-    auto ExpectedDbi = Dbi->build();
+    auto ExpectedDbi = Dbi->build(*File);
     if (!ExpectedDbi)
       return ExpectedDbi.takeError();
     File->Dbi = std::move(*ExpectedDbi);

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Fri Jul 15 17:16:56 2016
@@ -16,7 +16,6 @@
 ; EMPTY-NEXT:   Unknown1: 0
 ; EMPTY-NEXT:   BlockMapAddr: 24
 ; EMPTY-NEXT:   NumDirectoryBlocks: 1
-; EMPTY-NEXT:   BlockMapOffset: 98304
 ; EMPTY-NEXT:   DirectoryBlocks: [23]
 ; EMPTY-NEXT:   NumStreams: 17
 ; EMPTY-NEXT: }
@@ -952,7 +951,6 @@
 ; ALL:   Unknown1: 0
 ; ALL:   BlockMapAddr: 24
 ; ALL:   NumDirectoryBlocks: 1
-; ALL:   BlockMapOffset: 98304
 ; ALL:   DirectoryBlocks: [23]
 ; ALL:   NumStreams: 17
 ; ALL: }
@@ -1668,7 +1666,6 @@
 ; BIG-NEXT:   Unknown1: 0
 ; BIG-NEXT:   BlockMapAddr: 97
 ; BIG-NEXT:   NumDirectoryBlocks: 1
-; BIG-NEXT:   BlockMapOffset: 397312
 ; BIG-NEXT:   DirectoryBlocks: [96]
 ; BIG-NEXT:   NumStreams: 64
 ; BIG-NEXT: }

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test Fri Jul 15 17:16:56 2016
@@ -5,9 +5,13 @@
 ; the YAML, the PDB might be missing data required for any standard tool
 ; to recognize it.  Finally, it dumps the same set of fields from the newly
 ; constructed PDB to YAML, and verifies that the YAML is the same as the
-; original YAML generated from the good PDB.
+; original YAML generated from the good PDB.  Note that when doing the
+; final comparison it must dump the original and the new pdb without any
+; stream metadata, since the layout of the MSF file might be different
+; (for example if we don't write the entire stream)
 ;
 ; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -pdb-stream %p/Inputs/empty.pdb > %t.1
 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
-; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -pdb-stream %t.2 > %t.3
-; RUN: diff %t.1 %t.3
+; RUN: llvm-pdbdump pdb2yaml -pdb-stream %p/Inputs/empty.pdb > %t.3
+; RUN: llvm-pdbdump pdb2yaml -pdb-stream %t.2 > %t.4
+; RUN: diff %t.3 %t.4

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test Fri Jul 15 17:16:56 2016
@@ -13,7 +13,6 @@
 ; YAML-NEXT:     Unknown1:        0
 ; YAML-NEXT:     BlockMapAddr:    24
 ; YAML-NEXT:   NumDirectoryBlocks: 1
-; YAML-NEXT:   BlockMapOffset:  98304
 ; YAML-NEXT:   DirectoryBlocks:
 ; YAML-NEXT:     - 23
 ; YAML-NEXT:   NumStreams:      17

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Fri Jul 15 17:16:56 2016
@@ -101,7 +101,6 @@ Error LLVMOutputStyle::dumpFileHeaders()
   P.printNumber("Unknown1", File.getUnknown1());
   P.printNumber("BlockMapAddr", File.getBlockMapIndex());
   P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
-  P.printNumber("BlockMapOffset", File.getBlockMapOffset());
 
   // The directory is not contiguous.  Instead, the block map contains a
   // contiguous list of block numbers whose contents, when concatenated in

Modified: llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp Fri Jul 15 17:16:56 2016
@@ -115,16 +115,14 @@ void MappingTraits<PdbObject>::mapping(I
 void MappingTraits<MsfHeaders>::mapping(IO &IO, MsfHeaders &Obj) {
   IO.mapRequired("SuperBlock", Obj.SuperBlock);
   IO.mapRequired("NumDirectoryBlocks", Obj.NumDirectoryBlocks);
-  IO.mapRequired("BlockMapOffset", Obj.BlockMapOffset);
   IO.mapRequired("DirectoryBlocks", Obj.DirectoryBlocks);
   IO.mapRequired("NumStreams", Obj.NumStreams);
   IO.mapRequired("FileSize", Obj.FileSize);
 }
 
-void MappingTraits<PDBFile::SuperBlock>::mapping(IO &IO,
-                                                 PDBFile::SuperBlock &SB) {
+void MappingTraits<msf::SuperBlock>::mapping(IO &IO, msf::SuperBlock &SB) {
   if (!IO.outputting()) {
-    ::memcpy(SB.MagicBytes, MsfMagic, sizeof(MsfMagic));
+    ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic));
   }
 
   IO.mapRequired("BlockSize", SB.BlockSize);

Modified: llvm/trunk/tools/llvm-pdbdump/PdbYaml.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PdbYaml.h?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PdbYaml.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PdbYaml.h Fri Jul 15 17:16:56 2016
@@ -14,6 +14,7 @@
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
 #include "llvm/Support/Endian.h"
@@ -26,16 +27,15 @@ namespace pdb {
 
 namespace yaml {
 struct MsfHeaders {
-  PDBFile::SuperBlock SuperBlock;
+  msf::SuperBlock SuperBlock;
   uint32_t NumDirectoryBlocks;
-  uint32_t BlockMapOffset;
-  std::vector<support::ulittle32_t> DirectoryBlocks;
+  std::vector<uint32_t> DirectoryBlocks;
   uint32_t NumStreams;
   uint32_t FileSize;
 };
 
 struct StreamBlockList {
-  std::vector<support::ulittle32_t> Blocks;
+  std::vector<uint32_t> Blocks;
 };
 
 struct PdbInfoStream {
@@ -57,7 +57,7 @@ struct PdbDbiStream {
 
 struct PdbObject {
   Optional<MsfHeaders> Headers;
-  Optional<std::vector<support::ulittle32_t>> StreamSizes;
+  Optional<std::vector<uint32_t>> StreamSizes;
   Optional<std::vector<StreamBlockList>> StreamMap;
   Optional<PdbInfoStream> PdbStream;
   Optional<PdbDbiStream> DbiStream;
@@ -77,8 +77,8 @@ template <> struct MappingTraits<pdb::ya
   static void mapping(IO &IO, pdb::yaml::MsfHeaders &Obj);
 };
 
-template <> struct MappingTraits<pdb::PDBFile::SuperBlock> {
-  static void mapping(IO &IO, pdb::PDBFile::SuperBlock &SB);
+template <> struct MappingTraits<pdb::msf::SuperBlock> {
+  static void mapping(IO &IO, pdb::msf::SuperBlock &SB);
 };
 
 template <> struct MappingTraits<pdb::yaml::StreamBlockList> {
@@ -95,7 +95,7 @@ template <> struct MappingTraits<pdb::ya
 }
 }
 
-LLVM_YAML_IS_SEQUENCE_VECTOR(support::ulittle32_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
 
 #endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H

Modified: llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp Fri Jul 15 17:16:56 2016
@@ -23,8 +23,7 @@ using namespace llvm::pdb;
 YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
 
 Error YAMLOutputStyle::dump() {
-  if (opts::pdb2yaml::StreamDirectory || opts::pdb2yaml::PdbStream ||
-      opts::pdb2yaml::DbiStream)
+  if (opts::pdb2yaml::StreamDirectory)
     opts::pdb2yaml::StreamMetadata = true;
 
   if (auto EC = dumpFileHeaders())
@@ -54,7 +53,6 @@ Error YAMLOutputStyle::dumpFileHeaders()
   Obj.Headers.emplace();
   Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
   Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
-  Obj.Headers->BlockMapOffset = File.getBlockMapOffset();
   Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();
   auto Blocks = File.getDirectoryBlockArray();
   Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());
@@ -73,7 +71,9 @@ Error YAMLOutputStyle::dumpStreamMetadat
   if (!opts::pdb2yaml::StreamMetadata)
     return Error::success();
 
-  Obj.StreamSizes = File.getStreamSizes();
+  Obj.StreamSizes.emplace();
+  Obj.StreamSizes->assign(File.getStreamSizes().begin(),
+                          File.getStreamSizes().end());
   return Error::success();
 }
 
@@ -85,7 +85,7 @@ Error YAMLOutputStyle::dumpStreamDirecto
   Obj.StreamMap.emplace();
   for (auto &Stream : StreamMap) {
     pdb::yaml::StreamBlockList BlockList;
-    BlockList.Blocks = Stream;
+    BlockList.Blocks.assign(Stream.begin(), Stream.end());
     Obj.StreamMap->push_back(BlockList);
   }
 

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=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Fri Jul 15 17:16:56 2016
@@ -279,14 +279,12 @@ cl::opt<bool> StreamDirectory(
     "stream-directory",
     cl::desc("Dump each stream's block map (implies -stream-metadata)"),
     cl::sub(PdbToYamlSubcommand), cl::init(false));
-cl::opt<bool> PdbStream(
-    "pdb-stream",
-    cl::desc("Dump the PDB Stream (Stream 1) (implies -stream-metadata)"),
-    cl::sub(PdbToYamlSubcommand), cl::init(false));
-cl::opt<bool> DbiStream(
-    "dbi-stream",
-    cl::desc("Dump the DBI Stream (Stream 2) (implies -stream-metadata)"),
-    cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> PdbStream("pdb-stream",
+                        cl::desc("Dump the PDB Stream (Stream 1)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> DbiStream("dbi-stream",
+                        cl::desc("Dump the DBI Stream (Stream 2)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
 
 cl::list<std::string> InputFilename(cl::Positional,
                                     cl::desc("<input PDB file>"), cl::Required,
@@ -324,20 +322,37 @@ static void yamlToPdb(StringRef Path) {
       llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
   PDBFileBuilder Builder(std::move(FileByteStream));
 
-  ExitOnErr(Builder.setSuperBlock(YamlObj.Headers->SuperBlock));
-  if (YamlObj.StreamSizes.hasValue()) {
-    Builder.setStreamSizes(YamlObj.StreamSizes.getValue());
+  ExitOnErr(Builder.initialize(YamlObj.Headers->SuperBlock));
+  ExitOnErr(Builder.getMsfBuilder().setDirectoryBlocksHint(
+      YamlObj.Headers->DirectoryBlocks));
+  if (!YamlObj.StreamSizes.hasValue()) {
+    ExitOnErr(make_error<GenericError>(
+        generic_error_code::unspecified,
+        "Cannot generate a PDB when stream sizes are not known"));
   }
-  Builder.setDirectoryBlocks(YamlObj.Headers->DirectoryBlocks);
 
   if (YamlObj.StreamMap.hasValue()) {
-    std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
-    for (auto &E : YamlObj.StreamMap.getValue()) {
-      StreamMap.push_back(E.Blocks);
+    if (YamlObj.StreamMap->size() != YamlObj.StreamSizes->size()) {
+      ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
+                                         "YAML specifies different number of "
+                                         "streams in stream sizes and stream "
+                                         "map"));
+    }
+
+    auto &Sizes = *YamlObj.StreamSizes;
+    auto &Map = *YamlObj.StreamMap;
+    for (uint32_t I = 0; I < Sizes.size(); ++I) {
+      uint32_t Size = Sizes[I];
+      std::vector<uint32_t> Blocks;
+      for (auto E : Map[I].Blocks)
+        Blocks.push_back(E);
+      ExitOnErr(Builder.getMsfBuilder().addStream(Size, Blocks));
     }
-    Builder.setStreamMap(StreamMap);
   } else {
-    ExitOnErr(Builder.generateSimpleStreamMap());
+    auto &Sizes = *YamlObj.StreamSizes;
+    for (auto S : Sizes) {
+      ExitOnErr(Builder.getMsfBuilder().addStream(S));
+    }
   }
 
   if (YamlObj.PdbStream.hasValue()) {

Modified: llvm/trunk/unittests/DebugInfo/PDB/MsfBuilderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/PDB/MsfBuilderTest.cpp?rev=275627&r1=275626&r2=275627&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/PDB/MsfBuilderTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/PDB/MsfBuilderTest.cpp Fri Jul 15 17:16:56 2016
@@ -84,7 +84,8 @@ TEST_F(MsfBuilderTest, TestUsedBlocksMar
   // Allocate some extra blocks at the end so we can verify that they're free
   // after the initialization.
   std::vector<uint32_t> Blocks = {2, 3, 4, 5, 6, 7, 8, 9, 10};
-  auto ExpectedMsf = MsfBuilder::create(Allocator, 4096, Blocks.size() + 10);
+  auto ExpectedMsf =
+      MsfBuilder::create(Allocator, 4096, 2 + Blocks.size() + 10);
   EXPECT_EXPECTED(ExpectedMsf);
   auto &Msf = *ExpectedMsf;
 
@@ -267,7 +268,7 @@ TEST_F(MsfBuilderTest, TestBlockCountsWh
   }
 }
 
-TEST_F(MsfBuilderTest, TestBuildMsfLayout) {
+TEST_F(MsfBuilderTest, BuildMsfLayout) {
   // Test that we can generate an Msf Layout structure from a valid layout
   // specification.
   auto ExpectedMsf = MsfBuilder::create(Allocator, 4096);
@@ -298,3 +299,56 @@ TEST_F(MsfBuilderTest, TestBuildMsfLayou
     EXPECT_EQ(ExpectedNumBlocks, L.StreamMap[I].size());
   }
 }
+
+TEST_F(MsfBuilderTest, UseDirectoryBlockHint) {
+  Expected<MsfBuilder> ExpectedMsf =
+      MsfBuilder::create(Allocator, 4096, 4, false);
+  EXPECT_EXPECTED(ExpectedMsf);
+  auto &Msf = *ExpectedMsf;
+
+  EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({2}));
+  EXPECT_NO_ERROR(Msf.addStream(2048, {3}));
+
+  auto ExpectedLayout = Msf.build();
+  EXPECT_EXPECTED(ExpectedLayout);
+  Layout &L = *ExpectedLayout;
+  EXPECT_EQ(4U, L.SB->NumBlocks);
+  EXPECT_EQ(1U, L.DirectoryBlocks.size());
+  EXPECT_EQ(1U, L.StreamMap[0].size());
+
+  EXPECT_EQ(2U, L.DirectoryBlocks[0]);
+  EXPECT_EQ(3U, L.StreamMap[0].front());
+}
+
+TEST_F(MsfBuilderTest, DirectoryBlockHintInsufficient) {
+  Expected<MsfBuilder> ExpectedMsf = MsfBuilder::create(Allocator, 4096, 4);
+  EXPECT_EXPECTED(ExpectedMsf);
+  auto &Msf = *ExpectedMsf;
+
+  EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({2}));
+
+  uint32_t Size = 4096 * 4096 / 4;
+  EXPECT_NO_ERROR(Msf.addStream(Size));
+
+  auto ExpectedLayout = Msf.build();
+  EXPECT_EXPECTED(ExpectedLayout);
+  Layout &L = *ExpectedLayout;
+  EXPECT_EQ(2U, L.DirectoryBlocks.size());
+  EXPECT_EQ(2U, L.DirectoryBlocks[0]);
+}
+
+TEST_F(MsfBuilderTest, DirectoryBlockHintOverestimated) {
+  Expected<MsfBuilder> ExpectedMsf = MsfBuilder::create(Allocator, 4096, 4);
+  EXPECT_EXPECTED(ExpectedMsf);
+  auto &Msf = *ExpectedMsf;
+
+  EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({2, 3}));
+
+  EXPECT_NO_ERROR(Msf.addStream(2048));
+
+  auto ExpectedLayout = Msf.build();
+  EXPECT_EXPECTED(ExpectedLayout);
+  Layout &L = *ExpectedLayout;
+  EXPECT_EQ(1U, L.DirectoryBlocks.size());
+  EXPECT_EQ(2U, L.DirectoryBlocks[0]);
+}




More information about the llvm-commits mailing list