blob: 6fec0e32a8ae7f4641c7b6377027ed1584ea1d2a [file] [log] [blame]
Zachary Turnerdbeaea72016-07-11 21:45:26 +00001//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
11
Zachary Turnerfaa554b2016-07-15 22:16:56 +000012#include "llvm/ADT/BitVector.h"
13
Zachary Turnera3225b02016-07-29 20:56:36 +000014#include "llvm/DebugInfo/MSF/MSFBuilder.h"
15#include "llvm/DebugInfo/MSF/StreamInterface.h"
16#include "llvm/DebugInfo/MSF/StreamWriter.h"
Rui Ueyamafc22cef2016-09-30 20:34:44 +000017#include "llvm/DebugInfo/PDB/GenericError.h"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000018#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
19#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
20#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
21#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
22#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turnerc6d54da2016-09-09 17:46:17 +000023#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
24#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000025
26using namespace llvm;
27using namespace llvm::codeview;
Zachary Turnerbac69d32016-07-22 19:56:05 +000028using namespace llvm::msf;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000029using namespace llvm::pdb;
Zachary Turnerfaa554b2016-07-15 22:16:56 +000030using namespace llvm::support;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000031
Zachary Turnere109dc62016-07-22 19:56:26 +000032PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
33 : Allocator(Allocator) {}
Zachary Turnerdbeaea72016-07-11 21:45:26 +000034
Rui Ueyama5d6714e2016-09-30 20:52:12 +000035Error PDBFileBuilder::initialize(uint32_t BlockSize) {
36 auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
Zachary Turnerfaa554b2016-07-15 22:16:56 +000037 if (!ExpectedMsf)
38 return ExpectedMsf.takeError();
Rui Ueyama5d6714e2016-09-30 20:52:12 +000039 Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
Zachary Turnerdbeaea72016-07-11 21:45:26 +000040 return Error::success();
41}
42
Zachary Turnera3225b02016-07-29 20:56:36 +000043MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
Zachary Turnerfaa554b2016-07-15 22:16:56 +000044
Zachary Turnerdbeaea72016-07-11 21:45:26 +000045InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
46 if (!Info)
Zachary Turner620961d2016-09-14 23:00:02 +000047 Info = llvm::make_unique<InfoStreamBuilder>(*Msf);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000048 return *Info;
49}
50
51DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
52 if (!Dbi)
Zachary Turner620961d2016-09-14 23:00:02 +000053 Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000054 return *Dbi;
55}
56
Zachary Turnerc6d54da2016-09-09 17:46:17 +000057TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
58 if (!Tpi)
Zachary Turnerde9ba152016-09-15 18:22:31 +000059 Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
Zachary Turnerc6d54da2016-09-09 17:46:17 +000060 return *Tpi;
61}
62
Zachary Turnerde9ba152016-09-15 18:22:31 +000063TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
64 if (!Ipi)
65 Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
66 return *Ipi;
67}
68
Zachary Turnera3225b02016-07-29 20:56:36 +000069Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
Zachary Turnerdbeaea72016-07-11 21:45:26 +000070 if (Info) {
Zachary Turner620961d2016-09-14 23:00:02 +000071 if (auto EC = Info->finalizeMsfLayout())
Zachary Turnerfaa554b2016-07-15 22:16:56 +000072 return std::move(EC);
73 }
74 if (Dbi) {
Zachary Turner620961d2016-09-14 23:00:02 +000075 if (auto EC = Dbi->finalizeMsfLayout())
Zachary Turnerfaa554b2016-07-15 22:16:56 +000076 return std::move(EC);
77 }
Zachary Turnerc6d54da2016-09-09 17:46:17 +000078 if (Tpi) {
Zachary Turner620961d2016-09-14 23:00:02 +000079 if (auto EC = Tpi->finalizeMsfLayout())
Zachary Turnerc6d54da2016-09-09 17:46:17 +000080 return std::move(EC);
81 }
Zachary Turnerde9ba152016-09-15 18:22:31 +000082 if (Ipi) {
83 if (auto EC = Ipi->finalizeMsfLayout())
84 return std::move(EC);
85 }
Zachary Turnerfaa554b2016-07-15 22:16:56 +000086
Zachary Turner199f48a2016-07-28 19:11:09 +000087 return Msf->build();
88}
89
Rui Ueyamafc22cef2016-09-30 20:34:44 +000090Error PDBFileBuilder::commit(StringRef Filename) {
Zachary Turnerd66889c2016-07-28 19:12:28 +000091 auto ExpectedLayout = finalizeMsfLayout();
92 if (!ExpectedLayout)
93 return ExpectedLayout.takeError();
94 auto &Layout = *ExpectedLayout;
95
Rui Ueyamafc22cef2016-09-30 20:34:44 +000096 uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
97 auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
98 if (OutFileOrError.getError())
99 return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
100 Filename);
101 FileBufferByteStream Buffer(std::move(*OutFileOrError));
102 StreamWriter Writer(Buffer);
103
Zachary Turnerd66889c2016-07-28 19:12:28 +0000104 if (auto EC = Writer.writeObject(*Layout.SB))
105 return EC;
106 uint32_t BlockMapOffset =
107 msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
108 Writer.setOffset(BlockMapOffset);
109 if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
110 return EC;
111
112 auto DirStream =
113 WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
114 StreamWriter DW(*DirStream);
Zachary Turner9f73c202016-07-28 19:29:52 +0000115 if (auto EC =
116 DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size())))
Zachary Turnerd66889c2016-07-28 19:12:28 +0000117 return EC;
118
119 if (auto EC = DW.writeArray(Layout.StreamSizes))
120 return EC;
121
122 for (const auto &Blocks : Layout.StreamMap) {
123 if (auto EC = DW.writeArray(Blocks))
124 return EC;
125 }
126
127 if (Info) {
128 if (auto EC = Info->commit(Layout, Buffer))
129 return EC;
130 }
131
132 if (Dbi) {
133 if (auto EC = Dbi->commit(Layout, Buffer))
134 return EC;
135 }
136
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000137 if (Tpi) {
138 if (auto EC = Tpi->commit(Layout, Buffer))
139 return EC;
140 }
141
Zachary Turnerde9ba152016-09-15 18:22:31 +0000142 if (Ipi) {
143 if (auto EC = Ipi->commit(Layout, Buffer))
144 return EC;
145 }
146
Zachary Turnerd66889c2016-07-28 19:12:28 +0000147 return Buffer.commit();
Rui Ueyamafc22cef2016-09-30 20:34:44 +0000148}