aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp')
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp127
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);
+}