Refactor the PDB writing to use a builder approach

llvm-svn: 275110
This commit is contained in:
Zachary Turner 2016-07-11 21:45:26 +00:00
parent f6b9382467
commit dbeaea7b35
21 changed files with 658 additions and 179 deletions

View File

@ -29,11 +29,36 @@ struct coff_section;
}
namespace pdb {
class DbiStreamBuilder;
class PDBFile;
class ISectionContribVisitor;
class DbiStream {
struct HeaderInfo;
friend class DbiStreamBuilder;
struct HeaderInfo {
support::little32_t VersionSignature;
support::ulittle32_t VersionHeader;
support::ulittle32_t Age; // Should match InfoStream.
support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream #
support::ulittle16_t BuildNumber; // See DbiBuildNo structure.
support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream #
support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
support::ulittle16_t SymRecordStreamIndex; // Symbol records stream #
support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
support::little32_t ModiSubstreamSize; // Size of module info stream
support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream
support::little32_t SectionMapSize; // Size of sec. map substream
support::little32_t FileInfoSize; // Size of file info substream
support::little32_t TypeServerSize; // Size of type server map
support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info
support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?)
support::ulittle16_t Flags; // See DbiFlags enum.
support::ulittle16_t MachineType; // See PDB_MachineType enum.
support::ulittle32_t Reserved; // Pad to 64 bytes
};
public:
DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
@ -45,13 +70,16 @@ public:
uint16_t getPublicSymbolStreamIndex() const;
uint16_t getGlobalSymbolStreamIndex() const;
uint16_t getFlags() const;
bool isIncrementallyLinked() const;
bool hasCTypes() const;
bool isStripped() const;
uint16_t getBuildNumber() const;
uint16_t getBuildMajorVersion() const;
uint16_t getBuildMinorVersion() const;
uint16_t getPdbDllRbld() const;
uint32_t getPdbDllVersion() const;
uint32_t getSymRecordStreamIndex() const;

View File

@ -0,0 +1,55 @@
//===- DbiStreamBuilder.h - PDB Dbi Stream Creation -------------*- 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_PDBDBISTREAMBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
namespace llvm {
namespace pdb {
class DbiStream;
class PDBFile;
class DbiStreamBuilder {
public:
DbiStreamBuilder(PDBFile &File);
DbiStreamBuilder(const DbiStreamBuilder &) = delete;
DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
void setVersionHeader(PdbRaw_DbiVer V);
void setAge(uint32_t A);
void setBuildNumber(uint16_t B);
void setPdbDllVersion(uint16_t V);
void setPdbDllRbld(uint16_t R);
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
Expected<std::unique_ptr<DbiStream>> build();
private:
PDBFile &File;
Optional<PdbRaw_DbiVer> VerHeader;
uint32_t Age;
uint16_t BuildNumber;
uint16_t PdbDllVersion;
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
};
}
}
#endif

View File

@ -21,28 +21,33 @@
namespace llvm {
namespace pdb {
class InfoStreamBuilder;
class PDBFile;
class InfoStream {
friend class InfoStreamBuilder;
struct Header {
support::ulittle32_t Version;
support::ulittle32_t Signature;
support::ulittle32_t Age;
PDB_UniqueId Guid;
};
public:
InfoStream(std::unique_ptr<MappedBlockStream> Stream);
Error reload();
Error commit();
PdbRaw_ImplVer getVersion() const;
uint32_t getSignature() const;
uint32_t getAge() const;
PDB_UniqueId getGuid() const;
void setVersion(PdbRaw_ImplVer Ver);
void setSignature(uint32_t Sig);
void setAge(uint32_t Age);
void setGuid(PDB_UniqueId Guid);
uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
Error commit();
private:
std::unique_ptr<MappedBlockStream> Stream;

View File

@ -0,0 +1,50 @@
//===- InfoStreamBuilder.h - PDB Info Stream Creation -----------*- 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_PDBINFOSTREAMBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/NameMap.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(const InfoStreamBuilder &) = delete;
InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
void setVersion(PdbRaw_ImplVer V);
void setSignature(uint32_t S);
void setAge(uint32_t A);
void setGuid(PDB_UniqueId G);
Expected<std::unique_ptr<InfoStream>> build();
private:
IPDBFile &File;
Optional<PdbRaw_ImplVer> Ver;
Optional<uint32_t> Sig;
Optional<uint32_t> Age;
Optional<PDB_UniqueId> Guid;
Optional<NameMap> NamedStreams;
};
}
}
#endif

View File

@ -14,6 +14,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@ -24,7 +25,6 @@ namespace llvm {
namespace pdb {
class IPDBFile;
class IPDBStreamData;
class PDBFile;
class MappedBlockStream : public codeview::StreamInterface {
@ -45,6 +45,8 @@ public:
static Expected<std::unique_ptr<MappedBlockStream>>
createDirectoryStream(const PDBFile &File);
llvm::BumpPtrAllocator &getAllocator() { return Pool; }
protected:
MappedBlockStream(std::unique_ptr<IPDBStreamData> Data, const IPDBFile &File);

View File

@ -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/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
@ -31,6 +32,7 @@ class DbiStream;
class InfoStream;
class MappedBlockStream;
class NameHashTable;
class PDBFileBuilder;
class PublicsStream;
class SymbolStream;
class TpiStream;
@ -41,6 +43,8 @@ static const char MsfMagic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
'\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
@ -107,8 +111,6 @@ public:
return BlockNumber * BlockSize;
}
Expected<InfoStream &> emplacePDBInfoStream();
Expected<InfoStream &> getPDBInfoStream();
Expected<DbiStream &> getPDBDbiStream();
Expected<TpiStream &> getPDBTpiStream();
@ -117,14 +119,13 @@ public:
Expected<SymbolStream &> getPDBSymbolStream();
Expected<NameHashTable &> getStringTable();
Error setSuperBlock(const SuperBlock *Block);
void setStreamSizes(ArrayRef<support::ulittle32_t> Sizes);
void setDirectoryBlocks(ArrayRef<support::ulittle32_t> Directory);
void setStreamMap(std::vector<ArrayRef<support::ulittle32_t>> &Streams);
Error generateSimpleStreamMap();
Error commit();
private:
Error setSuperBlock(const SuperBlock *Block);
BumpPtrAllocator Allocator;
std::unique_ptr<codeview::StreamInterface> Buffer;
const PDBFile::SuperBlock *SB;
ArrayRef<support::ulittle32_t> StreamSizes;

View File

@ -0,0 +1,60 @@
//===- PDBFileBuilder.h - PDB File Creation ---------------------*- 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_PDBFILEBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include <memory>
#include <vector>
namespace llvm {
namespace codeview {
class StreamInterface;
}
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
class PDBFile;
class PDBFileBuilder {
public:
explicit PDBFileBuilder(
std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
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();
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;
};
}
}
#endif

View File

@ -29,16 +29,19 @@ endif()
add_pdb_impl_folder(Raw
Raw/DbiStream.cpp
Raw/DbiStreamBuilder.cpp
Raw/EnumTables.cpp
Raw/Hash.cpp
Raw/IndexedStreamData.cpp
Raw/InfoStream.cpp
Raw/InfoStreamBuilder.cpp
Raw/MappedBlockStream.cpp
Raw/ModInfo.cpp
Raw/ModStream.cpp
Raw/NameHashTable.cpp
Raw/NameMap.cpp
Raw/PDBFile.cpp
Raw/PDBFileBuilder.cpp
Raw/PublicsStream.cpp
Raw/RawError.cpp
Raw/RawSession.cpp

View File

@ -11,6 +11,7 @@
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
@ -53,31 +54,16 @@ const uint16_t BuildMinorShift = 0;
const uint16_t BuildMajorMask = 0x7F00;
const uint16_t BuildMajorShift = 8;
}
struct DbiStream::HeaderInfo {
little32_t VersionSignature;
ulittle32_t VersionHeader;
ulittle32_t Age; // Should match InfoStream.
ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream #
ulittle16_t BuildNumber; // See DbiBuildNo structure.
ulittle16_t PublicSymbolStreamIndex; // Public symbols stream #
ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
ulittle16_t SymRecordStreamIndex; // Symbol records stream #
ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
little32_t ModiSubstreamSize; // Size of module info stream
little32_t SecContrSubstreamSize; // Size of sec. contribution stream
little32_t SectionMapSize; // Size of sec. map substream
little32_t FileInfoSize; // Size of file info substream
little32_t TypeServerSize; // Size of type server map
ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
little32_t OptionalDbgHdrSize; // Size of DbgHeader info
little32_t ECSubstreamSize; // Size of EC stream (what is EC?)
ulittle16_t Flags; // See DbiFlags enum.
ulittle16_t MachineType; // See PDB_MachineType enum.
ulittle32_t Reserved; // Pad to 64 bytes
struct FileInfoSubstreamHeader {
ulittle16_t NumModules; // Total # of modules, should match number of
// records in the ModuleInfo substream.
ulittle16_t NumSourceFiles; // Total # of source files. This value is not
// accurate because PDB actually supports more
// than 64k source files, so we ignore it and
// compute the value from other stream fields.
};
}
template <typename ContribType>
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
@ -218,6 +204,8 @@ uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
return Header->GlobalSymbolStreamIndex;
}
uint16_t DbiStream::getFlags() const { return Header->Flags; }
bool DbiStream::isIncrementallyLinked() const {
return (Header->Flags & FlagIncrementalMask) != 0;
}
@ -230,6 +218,8 @@ bool DbiStream::isStripped() const {
return (Header->Flags & FlagStrippedMask) != 0;
}
uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
uint16_t DbiStream::getBuildMajorVersion() const {
return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift;
}
@ -238,6 +228,8 @@ uint16_t DbiStream::getBuildMinorVersion() const {
return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift;
}
uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
uint32_t DbiStream::getSymRecordStreamIndex() const {
@ -353,15 +345,6 @@ Error DbiStream::initializeSectionMapData() {
}
Error DbiStream::initializeFileInfo() {
struct FileInfoSubstreamHeader {
ulittle16_t NumModules; // Total # of modules, should match number of
// records in the ModuleInfo substream.
ulittle16_t NumSourceFiles; // Total # of source files. This value is not
// accurate because PDB actually supports more
// than 64k source files, so we ignore it and
// compute the value from other stream fields.
};
// The layout of the FileInfoSubstream is like this:
// struct {
// ulittle16_t NumModules;

View File

@ -0,0 +1,76 @@
//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- 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/DbiStreamBuilder.h"
#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
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) {}
void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build() {
if (!VerHeader.hasValue())
return make_error<RawError>(raw_error_code::unspecified,
"Missing DBI Stream Version");
auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, File);
if (!DbiS)
return DbiS.takeError();
auto DS = std::move(*DbiS);
DbiStream::HeaderInfo *H =
static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate(
sizeof(DbiStream::HeaderInfo),
llvm::AlignOf<DbiStream::HeaderInfo>::Alignment));
H->VersionHeader = *VerHeader;
H->VersionSignature = -1;
H->Age = Age;
H->BuildNumber = BuildNumber;
H->Flags = Flags;
H->PdbDllRbld = PdbDllRbld;
H->PdbDllVersion = PdbDllVersion;
H->MachineType = static_cast<uint16_t>(MachineType);
H->ECSubstreamSize = 0;
H->FileInfoSize = 0;
H->ModiSubstreamSize = 0;
H->OptionalDbgHdrSize = 0;
H->SecContrSubstreamSize = 0;
H->SectionMapSize = 0;
H->TypeServerSize = 0;
H->SymRecordStreamIndex = DbiStream::InvalidStreamIndex;
H->PublicSymbolStreamIndex = DbiStream::InvalidStreamIndex;
H->MFCTypeServerIndex = DbiStream::InvalidStreamIndex;
H->GlobalSymbolStreamIndex = DbiStream::InvalidStreamIndex;
auto Dbi = llvm::make_unique<DbiStream>(File, std::move(DS));
Dbi->Header = H;
return std::move(Dbi);
}

View File

@ -21,15 +21,6 @@ using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
namespace {
struct Header {
support::ulittle32_t Version;
support::ulittle32_t Signature;
support::ulittle32_t Age;
PDB_UniqueId Guid;
};
}
InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
: Stream(std::move(Stream)) {}
@ -84,16 +75,6 @@ uint32_t InfoStream::getAge() const { return Age; }
PDB_UniqueId InfoStream::getGuid() const { return Guid; }
void InfoStream::setVersion(PdbRaw_ImplVer Ver) {
Version = static_cast<uint32_t>(Ver);
}
void InfoStream::setSignature(uint32_t Sig) { Signature = Sig; }
void InfoStream::setAge(uint32_t Age) { this->Age = Age; }
void InfoStream::setGuid(PDB_UniqueId Guid) { this->Guid = Guid; }
Error InfoStream::commit() {
StreamWriter Writer(*Stream);
@ -106,4 +87,4 @@ Error InfoStream::commit() {
return EC;
return NamedStreams.commit(Writer);
}
}

View File

@ -0,0 +1,54 @@
//===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- 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/InfoStreamBuilder.h"
#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
InfoStreamBuilder::InfoStreamBuilder(IPDBFile &File) : File(File) {}
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
void InfoStreamBuilder::setSignature(uint32_t S) { Sig = S; }
void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
void InfoStreamBuilder::setGuid(PDB_UniqueId G) { Guid = G; }
Expected<std::unique_ptr<InfoStream>> InfoStreamBuilder::build() {
if (!Ver.hasValue())
return make_error<RawError>(raw_error_code::unspecified,
"Missing PDB Stream Version");
if (!Sig.hasValue())
return make_error<RawError>(raw_error_code::unspecified,
"Missing PDB Stream Signature");
if (!Age.hasValue())
return make_error<RawError>(raw_error_code::unspecified,
"Missing PDB Stream Age");
if (!Guid.hasValue())
return make_error<RawError>(raw_error_code::unspecified,
"Missing PDB Stream Guid");
auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, File);
if (!InfoS)
return InfoS.takeError();
auto Info = llvm::make_unique<InfoStream>(std::move(*InfoS));
Info->Version = *Ver;
Info->Signature = *Sig;
Info->Age = *Age;
Info->Guid = *Guid;
return std::move(Info);
}

View File

@ -173,17 +173,6 @@ llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
return DirectoryBlocks;
}
Expected<InfoStream &> PDBFile::emplacePDBInfoStream() {
if (Info)
Info.reset();
auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
if (!InfoS)
return InfoS.takeError();
Info = llvm::make_unique<InfoStream>(std::move(*InfoS));
return *Info;
}
Expected<InfoStream &> PDBFile::getPDBInfoStream() {
if (!Info) {
auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
@ -352,64 +341,6 @@ Error PDBFile::setSuperBlock(const SuperBlock *Block) {
return Error::success();
}
void PDBFile::setStreamSizes(ArrayRef<support::ulittle32_t> Sizes) {
StreamSizes = Sizes;
}
void PDBFile::setStreamMap(
std::vector<ArrayRef<support::ulittle32_t>> &Streams) {
StreamMap = Streams;
}
void PDBFile::setDirectoryBlocks(ArrayRef<support::ulittle32_t> Directory) {
DirectoryBlocks = Directory;
}
Error PDBFile::generateSimpleStreamMap() {
if (StreamSizes.empty())
return Error::success();
static std::vector<std::vector<support::ulittle32_t>> StaticMap;
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 = getBlockCount();
std::vector<support::ulittle32_t> ReservedBlocks;
ReservedBlocks.push_back(support::ulittle32_t(0));
ReservedBlocks.push_back(SB->BlockMapAddr);
ReservedBlocks.insert(ReservedBlocks.end(), DirectoryBlocks.begin(),
DirectoryBlocks.end());
uint32_t BlocksNeeded = 0;
for (auto Size : StreamSizes)
BlocksNeeded += bytesToBlocks(Size, getBlockSize());
support::ulittle32_t NextBlock(TotalFileBlocks - BlocksNeeded -
ReservedBlocks.size());
StaticMap.resize(StreamSizes.size());
for (uint32_t S = 0; S < StreamSizes.size(); ++S) {
uint32_t Size = StreamSizes[S];
uint32_t NumBlocks = bytesToBlocks(Size, 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 < getBlockCount());
ThisStream.push_back(NextBlock);
}
StreamMap.push_back(ThisStream);
}
return Error::success();
}
Error PDBFile::commit() {
StreamWriter Writer(*Buffer);

View File

@ -0,0 +1,127 @@
//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- 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/PDBFileBuilder.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
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);
}
return Error::success();
}
InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
if (!Info)
Info = llvm::make_unique<InfoStreamBuilder>(*File);
return *Info;
}
DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
if (!Dbi)
Dbi = llvm::make_unique<DbiStreamBuilder>(*File);
return *Dbi;
}
Expected<std::unique_ptr<PDBFile>> PDBFileBuilder::build() {
if (Info) {
auto ExpectedInfo = Info->build();
if (!ExpectedInfo)
return ExpectedInfo.takeError();
File->Info = std::move(*ExpectedInfo);
}
if (Dbi) {
auto ExpectedDbi = Dbi->build();
if (!ExpectedDbi)
return ExpectedDbi.takeError();
File->Dbi = std::move(*ExpectedDbi);
}
if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
return llvm::make_error<RawError>(
raw_error_code::corrupt_file,
"PDB Stream Age doesn't match Dbi Stream Age!");
return std::move(File);
}

View File

@ -74,7 +74,7 @@
; YAML-NEXT: Age: 1
; YAML-NEXT: Guid: '{0B355641-86A0-A249-896F-9988FAE52FF0}'
; YAML-NEXT: Signature: 1424295906
; YAML-NEXT: Version: 20000404
; YAML-NEXT: Version: VC70
; YAML-NEXT: ...
; NO-HEADERS: ---

View File

@ -53,9 +53,74 @@ template <> struct ScalarTraits<llvm::pdb::PDB_UniqueId> {
static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
};
template <> struct ScalarEnumerationTraits<llvm::pdb::PDB_Machine> {
static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) {
io.enumCase(Value, "Invalid", PDB_Machine::Invalid);
io.enumCase(Value, "Am33", PDB_Machine::Am33);
io.enumCase(Value, "Amd64", PDB_Machine::Amd64);
io.enumCase(Value, "Arm", PDB_Machine::Arm);
io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT);
io.enumCase(Value, "Ebc", PDB_Machine::Ebc);
io.enumCase(Value, "x86", PDB_Machine::x86);
io.enumCase(Value, "Ia64", PDB_Machine::Ia64);
io.enumCase(Value, "M32R", PDB_Machine::M32R);
io.enumCase(Value, "Mips16", PDB_Machine::Mips16);
io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu);
io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16);
io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP);
io.enumCase(Value, "R4000", PDB_Machine::R4000);
io.enumCase(Value, "SH3", PDB_Machine::SH3);
io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP);
io.enumCase(Value, "Thumb", PDB_Machine::Thumb);
io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2);
}
};
template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_DbiVer> {
static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) {
io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41);
io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50);
io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60);
io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70);
io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110);
}
};
template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_ImplVer> {
static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) {
io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2);
io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4);
io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41);
io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50);
io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98);
io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep);
io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70);
io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80);
io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110);
io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140);
}
};
}
}
void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
IO.mapOptional("MSF", Obj.Headers);
IO.mapOptional("StreamSizes", Obj.StreamSizes);
IO.mapOptional("StreamMap", Obj.StreamMap);
IO.mapOptional("PdbStream", Obj.PdbStream);
IO.mapOptional("DbiStream", Obj.DbiStream);
}
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) {
if (!IO.outputting()) {
@ -74,25 +139,19 @@ void MappingTraits<StreamBlockList>::mapping(IO &IO, StreamBlockList &SB) {
IO.mapRequired("Stream", SB.Blocks);
}
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<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
IO.mapOptional("MSF", Obj.Headers);
IO.mapOptional("StreamSizes", Obj.StreamSizes);
IO.mapOptional("StreamMap", Obj.StreamMap);
IO.mapOptional("PdbStream", Obj.PdbStream);
}
void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) {
IO.mapRequired("Age", Obj.Age);
IO.mapRequired("Guid", Obj.Guid);
IO.mapRequired("Signature", Obj.Signature);
IO.mapRequired("Version", Obj.Version);
}
}
void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
IO.mapRequired("VerHeader", Obj.VerHeader);
IO.mapRequired("Age", Obj.Age);
IO.mapRequired("BuildNumber", Obj.BuildNumber);
IO.mapRequired("PdbDllVersion", Obj.PdbDllVersion);
IO.mapRequired("PdbDllRbld", Obj.PdbDllRbld);
IO.mapRequired("Flags", Obj.Flags);
IO.mapRequired("MachineType", Obj.MachineType);
}

View File

@ -39,17 +39,28 @@ struct StreamBlockList {
};
struct PdbInfoStream {
uint32_t Version;
PdbRaw_ImplVer Version;
uint32_t Signature;
uint32_t Age;
PDB_UniqueId Guid;
};
struct PdbDbiStream {
PdbRaw_DbiVer VerHeader;
uint32_t Age;
uint16_t BuildNumber;
uint32_t PdbDllVersion;
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
};
struct PdbObject {
Optional<MsfHeaders> Headers;
Optional<std::vector<support::ulittle32_t>> StreamSizes;
Optional<std::vector<StreamBlockList>> StreamMap;
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
};
}
}
@ -58,6 +69,14 @@ struct PdbObject {
namespace llvm {
namespace yaml {
template <> struct MappingTraits<pdb::yaml::PdbObject> {
static void mapping(IO &IO, pdb::yaml::PdbObject &Obj);
};
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);
};
@ -66,17 +85,13 @@ template <> struct MappingTraits<pdb::yaml::StreamBlockList> {
static void mapping(IO &IO, pdb::yaml::StreamBlockList &SB);
};
template <> struct MappingTraits<pdb::yaml::MsfHeaders> {
static void mapping(IO &IO, pdb::yaml::MsfHeaders &Obj);
};
template <> struct MappingTraits<pdb::yaml::PdbObject> {
static void mapping(IO &IO, pdb::yaml::PdbObject &Obj);
};
template <> struct MappingTraits<pdb::yaml::PdbInfoStream> {
static void mapping(IO &IO, pdb::yaml::PdbInfoStream &Obj);
};
template <> struct MappingTraits<pdb::yaml::PdbDbiStream> {
static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj);
};
}
}

View File

@ -12,6 +12,7 @@
#include "PdbYaml.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@ -22,7 +23,8 @@ using namespace llvm::pdb;
YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
Error YAMLOutputStyle::dump() {
if (opts::pdb2yaml::StreamDirectory || opts::pdb2yaml::PdbStream)
if (opts::pdb2yaml::StreamDirectory || opts::pdb2yaml::PdbStream ||
opts::pdb2yaml::DbiStream)
opts::pdb2yaml::StreamMetadata = true;
if (auto EC = dumpFileHeaders())
@ -37,6 +39,9 @@ Error YAMLOutputStyle::dump() {
if (auto EC = dumpPDBStream())
return EC;
if (auto EC = dumpDbiStream())
return EC;
flush();
return Error::success();
}
@ -105,6 +110,26 @@ Error YAMLOutputStyle::dumpPDBStream() {
return Error::success();
}
Error YAMLOutputStyle::dumpDbiStream() {
if (!opts::pdb2yaml::DbiStream)
return Error::success();
auto DbiS = File.getPDBDbiStream();
if (!DbiS)
return DbiS.takeError();
auto &DS = DbiS.get();
Obj.DbiStream.emplace();
Obj.DbiStream->Age = DS.getAge();
Obj.DbiStream->BuildNumber = DS.getBuildNumber();
Obj.DbiStream->Flags = DS.getFlags();
Obj.DbiStream->MachineType = DS.getMachineType();
Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
Obj.DbiStream->VerHeader = DS.getDbiVersion();
return Error::success();
}
void YAMLOutputStyle::flush() {
Out << Obj;
outs().flush();

View File

@ -30,6 +30,7 @@ private:
Error dumpStreamMetadata();
Error dumpStreamDirectory();
Error dumpPDBStream();
Error dumpDbiStream();
void flush();

View File

@ -40,8 +40,12 @@
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
@ -279,6 +283,10 @@ 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::list<std::string> InputFilename(cl::Positional,
cl::desc("<input PDB file>"), cl::Required,
@ -314,34 +322,48 @@ static void yamlToPdb(StringRef Path) {
auto FileByteStream =
llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
PDBFile Pdb(std::move(FileByteStream));
ExitOnErr(Pdb.setSuperBlock(&YamlObj.Headers->SuperBlock));
PDBFileBuilder Builder(std::move(FileByteStream));
ExitOnErr(Builder.setSuperBlock(YamlObj.Headers->SuperBlock));
if (YamlObj.StreamSizes.hasValue()) {
Pdb.setStreamSizes(YamlObj.StreamSizes.getValue());
Builder.setStreamSizes(YamlObj.StreamSizes.getValue());
}
Pdb.setDirectoryBlocks(YamlObj.Headers->DirectoryBlocks);
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);
}
Pdb.setStreamMap(StreamMap);
Builder.setStreamMap(StreamMap);
} else {
ExitOnErr(Pdb.generateSimpleStreamMap());
ExitOnErr(Builder.generateSimpleStreamMap());
}
if (YamlObj.PdbStream.hasValue()) {
auto IS = Pdb.emplacePDBInfoStream();
ExitOnErr(IS.takeError());
auto &InfoS = IS.get();
InfoS.setAge(YamlObj.PdbStream->Age);
InfoS.setGuid(YamlObj.PdbStream->Guid);
InfoS.setSignature(YamlObj.PdbStream->Signature);
InfoS.setVersion(static_cast<PdbRaw_ImplVer>(YamlObj.PdbStream->Version));
auto &InfoBuilder = Builder.getInfoBuilder();
InfoBuilder.setAge(YamlObj.PdbStream->Age);
InfoBuilder.setGuid(YamlObj.PdbStream->Guid);
InfoBuilder.setSignature(YamlObj.PdbStream->Signature);
InfoBuilder.setVersion(YamlObj.PdbStream->Version);
}
ExitOnErr(Pdb.commit());
if (YamlObj.DbiStream.hasValue()) {
auto &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setAge(YamlObj.DbiStream->Age);
DbiBuilder.setBuildNumber(YamlObj.DbiStream->BuildNumber);
DbiBuilder.setFlags(YamlObj.DbiStream->Flags);
DbiBuilder.setMachineType(YamlObj.DbiStream->MachineType);
DbiBuilder.setPdbDllRbld(YamlObj.DbiStream->PdbDllRbld);
DbiBuilder.setPdbDllVersion(YamlObj.DbiStream->PdbDllVersion);
DbiBuilder.setVersionHeader(YamlObj.DbiStream->VerHeader);
}
auto Pdb = Builder.build();
ExitOnErr(Pdb.takeError());
auto &PdbFile = *Pdb;
ExitOnErr(PdbFile->commit());
}
static void pdb2Yaml(StringRef Path) {

View File

@ -61,6 +61,7 @@ extern llvm::cl::opt<bool> NoFileHeaders;
extern llvm::cl::opt<bool> StreamMetadata;
extern llvm::cl::opt<bool> StreamDirectory;
extern llvm::cl::opt<bool> PdbStream;
extern llvm::cl::opt<bool> DbiStream;
extern llvm::cl::list<std::string> InputFilename;
}
}