[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.

llvm-svn: 275627
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index d4d6fa8..b5a2bc1 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -42,6 +42,7 @@
   Raw/MsfCommon.cpp
   Raw/NameHashTable.cpp
   Raw/NameMap.cpp
+  Raw/NameMapBuilder.cpp
   Raw/PDBFile.cpp
   Raw/PDBFileBuilder.cpp
   Raw/PublicsStream.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
index bfe0251..3c0586c 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
@@ -182,9 +182,11 @@
     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 @@
 }
 
 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 @@
 
 // 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 @@
 
 // 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::initializeSectionMapData() {
+  if (SecMapSubstream.getLength() == 0)
+    return Error::success();
+
   StreamReader SMReader(SecMapSubstream);
   const SecMapHeader *Header;
   if (auto EC = SMReader.readObject(Header))
@@ -357,6 +371,9 @@
   // 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 @@
   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();
+}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
index ff5ce61..34ff8ae 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
@@ -18,9 +18,9 @@
 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::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");
diff --git a/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
index e2f85ab..c33a764 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
@@ -27,7 +27,7 @@
 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 @@
 Error InfoStream::commit() {
   StreamWriter Writer(*Stream);
 
-  Header H;
+  HeaderInfo H;
   H.Age = Age;
   H.Signature = Signature;
   H.Version = Version;
@@ -87,4 +87,4 @@
     return EC;
 
   return NamedStreams.commit(Writer);
-}
\ No newline at end of file
+}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
index 21042e9..5a0e835 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
@@ -18,7 +18,7 @@
 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::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");
diff --git a/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
index ab739d3..fecefbf 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
@@ -24,7 +24,7 @@
                        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 @@
   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 @@
   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
diff --git a/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
new file mode 100644
index 0000000..fe033c3
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
@@ -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);
+}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
index 2aa4d4c..8b09dc5 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
@@ -53,7 +53,7 @@
 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 @@
 
 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 @@
         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 @@
     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 @@
   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();
 }
 
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
index f859c1f..b1ae760 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
@@ -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))) {}
+    std::unique_ptr<codeview::StreamInterface> FileBuffer)
+    : File(llvm::make_unique<PDBFile>(std::move(FileBuffer))) {}
 
-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);
-}
+Error PDBFileBuilder::initialize(const msf::SuperBlock &Super) {
+  auto ExpectedMsf =
+      MsfBuilder::create(File->Allocator, Super.BlockSize, Super.NumBlocks);
+  if (!ExpectedMsf)
+    return ExpectedMsf.takeError();
 
-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;
-}
-
-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);
-  }
+  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);