summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/DebugInfo/CodeView/StreamArray.h12
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h7
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h2
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h13
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h5
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h34
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h41
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h13
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp31
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp13
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp6
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp9
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp47
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp26
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp53
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp115
-rw-r--r--llvm/test/DebugInfo/PDB/pdbdump-headers.test3
-rw-r--r--llvm/test/DebugInfo/PDB/pdbdump-write.test10
-rw-r--r--llvm/test/DebugInfo/PDB/pdbdump-yaml.test1
-rw-r--r--llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp1
-rw-r--r--llvm/tools/llvm-pdbdump/PdbYaml.cpp6
-rw-r--r--llvm/tools/llvm-pdbdump/PdbYaml.h16
-rw-r--r--llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp10
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp49
-rw-r--r--llvm/unittests/DebugInfo/PDB/MsfBuilderTest.cpp58
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]);
+}
OpenPOWER on IntegriCloud