diff options
Diffstat (limited to 'llvm')
26 files changed, 344 insertions, 238 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h index b6ecc75e439..0b9349aac75 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h @@ -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() {} diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h index ab4300858ce..2c7350f3c3e 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h @@ -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; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h index 9cca4877709..1980bec7153 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h @@ -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; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h index e8ee572c1a0..872f300e7e4 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h @@ -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;  };  }  } diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h index b2b4c7ab496..707d3d84072 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h @@ -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; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h new file mode 100644 index 00000000000..698e767d9e6 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h @@ -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 diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index 71d7c6144c3..82551971dda 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -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; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h index ba7ca935e5f..47c755b4326 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h @@ -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;  };  }  } diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index d4d6fa80bc6..b5a2bc1600f 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -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 diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp index bfe0251f4ce..3c0586c728f 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -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::visitSectionContributions(  }  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::initializeSectionContributionData() {  // 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::initializeSectionHeadersData() {  // 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::getFileNameForIndex(uint32_t Index) const {    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 ff5ce61c212..34ff8ae3a90 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp @@ -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 F) { Flags = F; }  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 e2f85ab880f..c33a764587c 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp @@ -27,7 +27,7 @@ InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)  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 { return Guid; }  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 +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp index 21042e9a534..5a0e835dd56 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp @@ -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 A) { Age = A; }  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 ab739d339a9..fecefbfeb8d 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp @@ -24,7 +24,7 @@ MsfBuilder::MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,                         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_t Addr) {    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 diff --git a/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp new file mode 100644 index 00000000000..fe033c368e7 --- /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 2aa4d4c426f..8b09dc57cde 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -53,7 +53,7 @@ uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }  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 { return Buffer->getLength(); }  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 BlockIndex, uint32_t Offset,          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::getStringTable() {    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 f859c1fcc2e..b1ae760c6fb 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))) {} - -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; -} - -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); -  } +    std::unique_ptr<codeview::StreamInterface> FileBuffer) +    : File(llvm::make_unique<PDBFile>(std::move(FileBuffer))) {} + +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); diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index 80914cbe61a..dabce470852 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -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: } diff --git a/llvm/test/DebugInfo/PDB/pdbdump-write.test b/llvm/test/DebugInfo/PDB/pdbdump-write.test index 0421ef1e3e6..09358932941 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-write.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-write.test @@ -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 diff --git a/llvm/test/DebugInfo/PDB/pdbdump-yaml.test b/llvm/test/DebugInfo/PDB/pdbdump-yaml.test index a7394beb8cc..e0029d83517 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-yaml.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-yaml.test @@ -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 diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index d8eefa08377..6fee3a2b026 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -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 diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp index a341ab07308..6525e3c165b 100644 --- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp +++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp @@ -115,16 +115,14 @@ void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {  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); diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.h b/llvm/tools/llvm-pdbdump/PdbYaml.h index 91c0a585926..8a964a354c0 100644 --- a/llvm/tools/llvm-pdbdump/PdbYaml.h +++ b/llvm/tools/llvm-pdbdump/PdbYaml.h @@ -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::yaml::MsfHeaders> {    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::yaml::PdbDbiStream> {  }  } -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 diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index aa68128cd80..e216ab98c13 100644 --- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -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::dumpStreamMetadata() {    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::dumpStreamDirectory() {    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);    } diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 5a3ced37a9d..467b5bfe1b6 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -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()) { diff --git a/llvm/unittests/DebugInfo/PDB/MsfBuilderTest.cpp b/llvm/unittests/DebugInfo/PDB/MsfBuilderTest.cpp index f0b48ec1577..d20f5e52d88 100644 --- a/llvm/unittests/DebugInfo/PDB/MsfBuilderTest.cpp +++ b/llvm/unittests/DebugInfo/PDB/MsfBuilderTest.cpp @@ -84,7 +84,8 @@ TEST_F(MsfBuilderTest, TestUsedBlocksMarkedAsUsed) {    // 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, TestBlockCountsWhenAddingStreams) {    }  } -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, TestBuildMsfLayout) {      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]); +}  | 

