diff options
author | Zachary Turner <zturner@google.com> | 2016-07-11 21:45:26 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-07-11 21:45:26 +0000 |
commit | dbeaea7b357fb4343d01ffa466f3dcab1e57d392 (patch) | |
tree | f1fd778564c5e85b31e96504ee26b49424b00823 /llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp | |
parent | f6b93824677a9aaab59989f7f402010fda6bd63c (diff) | |
download | llvm-dbeaea7b357fb4343d01ffa466f3dcab1e57d392.zip llvm-dbeaea7b357fb4343d01ffa466f3dcab1e57d392.tar.gz llvm-dbeaea7b357fb4343d01ffa466f3dcab1e57d392.tar.bz2 |
Refactor the PDB writing to use a builder approach
llvm-svn: 275110
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp new file mode 100644 index 0000000..f859c1f --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp @@ -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); +} |