blob: 40e3c7901a931078cb49d0f973d9169042e14384 [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"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000017#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
18#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
19#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
20#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
21#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turnerc6d54da2016-09-09 17:46:17 +000022#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
23#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000024
25using namespace llvm;
26using namespace llvm::codeview;
Zachary Turnerbac69d32016-07-22 19:56:05 +000027using namespace llvm::msf;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000028using namespace llvm::pdb;
Zachary Turnerfaa554b2016-07-15 22:16:56 +000029using namespace llvm::support;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000030
Zachary Turnere109dc62016-07-22 19:56:26 +000031PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
32 : Allocator(Allocator) {}
Zachary Turnerdbeaea72016-07-11 21:45:26 +000033
Zachary Turnerfaa554b2016-07-15 22:16:56 +000034Error PDBFileBuilder::initialize(const msf::SuperBlock &Super) {
35 auto ExpectedMsf =
Zachary Turnera3225b02016-07-29 20:56:36 +000036 MSFBuilder::create(Allocator, Super.BlockSize, Super.NumBlocks);
Zachary Turnerfaa554b2016-07-15 22:16:56 +000037 if (!ExpectedMsf)
38 return ExpectedMsf.takeError();
Zachary Turnerdbeaea72016-07-11 21:45:26 +000039
Zachary Turnerfaa554b2016-07-15 22:16:56 +000040 auto &MsfResult = *ExpectedMsf;
41 if (auto EC = MsfResult.setBlockMapAddr(Super.BlockMapAddr))
42 return EC;
Zachary Turnera3225b02016-07-29 20:56:36 +000043 Msf = llvm::make_unique<MSFBuilder>(std::move(MsfResult));
Zachary Turnerb927e022016-07-15 22:17:19 +000044 Msf->setFreePageMap(Super.FreeBlockMapBlock);
45 Msf->setUnknown1(Super.Unknown1);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000046 return Error::success();
47}
48
Zachary Turnera3225b02016-07-29 20:56:36 +000049MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
Zachary Turnerfaa554b2016-07-15 22:16:56 +000050
Zachary Turnerdbeaea72016-07-11 21:45:26 +000051InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
52 if (!Info)
Zachary Turner620961d2016-09-14 23:00:02 +000053 Info = llvm::make_unique<InfoStreamBuilder>(*Msf);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000054 return *Info;
55}
56
57DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
58 if (!Dbi)
Zachary Turner620961d2016-09-14 23:00:02 +000059 Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000060 return *Dbi;
61}
62
Zachary Turnerc6d54da2016-09-09 17:46:17 +000063TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
64 if (!Tpi)
Zachary Turner620961d2016-09-14 23:00:02 +000065 Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf);
Zachary Turnerc6d54da2016-09-09 17:46:17 +000066 return *Tpi;
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 Turnerfaa554b2016-07-15 22:16:56 +000082
Zachary Turner199f48a2016-07-28 19:11:09 +000083 return Msf->build();
84}
85
86Expected<std::unique_ptr<PDBFile>>
Zachary Turnerd66889c2016-07-28 19:12:28 +000087PDBFileBuilder::build(std::unique_ptr<msf::WritableStream> PdbFileBuffer) {
Zachary Turner199f48a2016-07-28 19:11:09 +000088 auto ExpectedLayout = finalizeMsfLayout();
Zachary Turnerfaa554b2016-07-15 22:16:56 +000089 if (!ExpectedLayout)
90 return ExpectedLayout.takeError();
91
Zachary Turnere109dc62016-07-22 19:56:26 +000092 auto File = llvm::make_unique<PDBFile>(std::move(PdbFileBuffer), Allocator);
Zachary Turnerd66889c2016-07-28 19:12:28 +000093 File->ContainerLayout = *ExpectedLayout;
Zachary Turnerfaa554b2016-07-15 22:16:56 +000094
95 if (Info) {
Zachary Turnerd66889c2016-07-28 19:12:28 +000096 auto ExpectedInfo = Info->build(*File, *PdbFileBuffer);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000097 if (!ExpectedInfo)
98 return ExpectedInfo.takeError();
99 File->Info = std::move(*ExpectedInfo);
100 }
101
102 if (Dbi) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000103 auto ExpectedDbi = Dbi->build(*File, *PdbFileBuffer);
Zachary Turnerdbeaea72016-07-11 21:45:26 +0000104 if (!ExpectedDbi)
105 return ExpectedDbi.takeError();
106 File->Dbi = std::move(*ExpectedDbi);
107 }
108
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000109 if (Tpi) {
110 auto ExpectedTpi = Tpi->build(*File, *PdbFileBuffer);
111 if (!ExpectedTpi)
112 return ExpectedTpi.takeError();
113 File->Tpi = std::move(*ExpectedTpi);
114 }
115
Zachary Turnerdbeaea72016-07-11 21:45:26 +0000116 if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
117 return llvm::make_error<RawError>(
118 raw_error_code::corrupt_file,
119 "PDB Stream Age doesn't match Dbi Stream Age!");
120
121 return std::move(File);
122}
Zachary Turnerd66889c2016-07-28 19:12:28 +0000123
124Error PDBFileBuilder::commit(const msf::WritableStream &Buffer) {
125 StreamWriter Writer(Buffer);
126 auto ExpectedLayout = finalizeMsfLayout();
127 if (!ExpectedLayout)
128 return ExpectedLayout.takeError();
129 auto &Layout = *ExpectedLayout;
130
131 if (auto EC = Writer.writeObject(*Layout.SB))
132 return EC;
133 uint32_t BlockMapOffset =
134 msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
135 Writer.setOffset(BlockMapOffset);
136 if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
137 return EC;
138
139 auto DirStream =
140 WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
141 StreamWriter DW(*DirStream);
Zachary Turner9f73c202016-07-28 19:29:52 +0000142 if (auto EC =
143 DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size())))
Zachary Turnerd66889c2016-07-28 19:12:28 +0000144 return EC;
145
146 if (auto EC = DW.writeArray(Layout.StreamSizes))
147 return EC;
148
149 for (const auto &Blocks : Layout.StreamMap) {
150 if (auto EC = DW.writeArray(Blocks))
151 return EC;
152 }
153
154 if (Info) {
155 if (auto EC = Info->commit(Layout, Buffer))
156 return EC;
157 }
158
159 if (Dbi) {
160 if (auto EC = Dbi->commit(Layout, Buffer))
161 return EC;
162 }
163
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000164 if (Tpi) {
165 if (auto EC = Tpi->commit(Layout, Buffer))
166 return EC;
167 }
168
Zachary Turnerd66889c2016-07-28 19:12:28 +0000169 return Buffer.commit();
170}