blob: 4dd965c69071e4f851ebc303d4882ece4c159ef4 [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
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000010#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000011
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"
Rui Ueyamafc22cef2016-09-30 20:34:44 +000015#include "llvm/DebugInfo/PDB/GenericError.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000016#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
17#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
18#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
19#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
Zachary Turnere204a6c2017-05-02 18:00:13 +000020#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000021#include "llvm/DebugInfo/PDB/Native/RawError.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000022#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
23#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
Zachary Turnerd9dc2822017-03-02 20:52:51 +000024#include "llvm/Support/BinaryStream.h"
25#include "llvm/Support/BinaryStreamWriter.h"
Zachary Turnerdbeaea72016-07-11 21:45:26 +000026
27using namespace llvm;
28using namespace llvm::codeview;
Zachary Turnerbac69d32016-07-22 19:56:05 +000029using namespace llvm::msf;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000030using namespace llvm::pdb;
Zachary Turnerfaa554b2016-07-15 22:16:56 +000031using namespace llvm::support;
Zachary Turnerdbeaea72016-07-11 21:45:26 +000032
Zachary Turnere109dc62016-07-22 19:56:26 +000033PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
34 : Allocator(Allocator) {}
Zachary Turnerdbeaea72016-07-11 21:45:26 +000035
Rui Ueyama5d6714e2016-09-30 20:52:12 +000036Error PDBFileBuilder::initialize(uint32_t BlockSize) {
37 auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
Zachary Turnerfaa554b2016-07-15 22:16:56 +000038 if (!ExpectedMsf)
39 return ExpectedMsf.takeError();
Rui Ueyama5d6714e2016-09-30 20:52:12 +000040 Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
Zachary Turnerdbeaea72016-07-11 21:45:26 +000041 return Error::success();
42}
43
Zachary Turnera3225b02016-07-29 20:56:36 +000044MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
Zachary Turnerfaa554b2016-07-15 22:16:56 +000045
Zachary Turnerdbeaea72016-07-11 21:45:26 +000046InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
47 if (!Info)
Zachary Turner760ad4d2017-01-20 22:42:09 +000048 Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000049 return *Info;
50}
51
52DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
53 if (!Dbi)
Zachary Turner620961d2016-09-14 23:00:02 +000054 Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
Zachary Turnerdbeaea72016-07-11 21:45:26 +000055 return *Dbi;
56}
57
Zachary Turnerc6d54da2016-09-09 17:46:17 +000058TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
59 if (!Tpi)
Zachary Turnerde9ba152016-09-15 18:22:31 +000060 Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
Zachary Turnerc6d54da2016-09-09 17:46:17 +000061 return *Tpi;
62}
63
Zachary Turnerde9ba152016-09-15 18:22:31 +000064TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
65 if (!Ipi)
66 Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
67 return *Ipi;
68}
69
Zachary Turnere204a6c2017-05-02 18:00:13 +000070PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
71 return Strings;
72}
Zachary Turner760ad4d2017-01-20 22:42:09 +000073
74Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
75 auto ExpectedStream = Msf->addStream(Size);
76 if (!ExpectedStream)
77 return ExpectedStream.takeError();
78 NamedStreams.set(Name, *ExpectedStream);
79 return Error::success();
80}
81
82Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
Zachary Turnerc504ae32017-05-03 15:58:37 +000083 uint32_t StringsLen = Strings.calculateSerializedSize();
Zachary Turner760ad4d2017-01-20 22:42:09 +000084
Zachary Turnerc504ae32017-05-03 15:58:37 +000085 if (auto EC = addNamedStream("/names", StringsLen))
Zachary Turner760ad4d2017-01-20 22:42:09 +000086 return std::move(EC);
87 if (auto EC = addNamedStream("/LinkInfo", 0))
88 return std::move(EC);
89 if (auto EC = addNamedStream("/src/headerblock", 0))
90 return std::move(EC);
91
Zachary Turnerdbeaea72016-07-11 21:45:26 +000092 if (Info) {
Zachary Turner620961d2016-09-14 23:00:02 +000093 if (auto EC = Info->finalizeMsfLayout())
Zachary Turnerfaa554b2016-07-15 22:16:56 +000094 return std::move(EC);
95 }
96 if (Dbi) {
Zachary Turner620961d2016-09-14 23:00:02 +000097 if (auto EC = Dbi->finalizeMsfLayout())
Zachary Turnerfaa554b2016-07-15 22:16:56 +000098 return std::move(EC);
99 }
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000100 if (Tpi) {
Zachary Turner620961d2016-09-14 23:00:02 +0000101 if (auto EC = Tpi->finalizeMsfLayout())
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000102 return std::move(EC);
103 }
Zachary Turnerde9ba152016-09-15 18:22:31 +0000104 if (Ipi) {
105 if (auto EC = Ipi->finalizeMsfLayout())
106 return std::move(EC);
107 }
Zachary Turnerfaa554b2016-07-15 22:16:56 +0000108
Zachary Turner199f48a2016-07-28 19:11:09 +0000109 return Msf->build();
110}
111
Zachary Turnerc504ae32017-05-03 15:58:37 +0000112Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
113 uint32_t SN = 0;
114 if (!NamedStreams.get(Name, SN))
115 return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
116 return SN;
117}
118
Rui Ueyamafc22cef2016-09-30 20:34:44 +0000119Error PDBFileBuilder::commit(StringRef Filename) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000120 auto ExpectedLayout = finalizeMsfLayout();
121 if (!ExpectedLayout)
122 return ExpectedLayout.takeError();
123 auto &Layout = *ExpectedLayout;
124
Rui Ueyamafc22cef2016-09-30 20:34:44 +0000125 uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
126 auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
127 if (OutFileOrError.getError())
128 return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
129 Filename);
Zachary Turner695ed562017-02-28 00:04:07 +0000130 FileBufferByteStream Buffer(std::move(*OutFileOrError),
131 llvm::support::little);
Zachary Turner120faca2017-02-27 22:11:43 +0000132 BinaryStreamWriter Writer(Buffer);
Rui Ueyamafc22cef2016-09-30 20:34:44 +0000133
Zachary Turnerd66889c2016-07-28 19:12:28 +0000134 if (auto EC = Writer.writeObject(*Layout.SB))
135 return EC;
136 uint32_t BlockMapOffset =
137 msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
138 Writer.setOffset(BlockMapOffset);
139 if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
140 return EC;
141
142 auto DirStream =
143 WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
Zachary Turner120faca2017-02-27 22:11:43 +0000144 BinaryStreamWriter DW(*DirStream);
Zachary Turner695ed562017-02-28 00:04:07 +0000145 if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
Zachary Turnerd66889c2016-07-28 19:12:28 +0000146 return EC;
147
148 if (auto EC = DW.writeArray(Layout.StreamSizes))
149 return EC;
150
151 for (const auto &Blocks : Layout.StreamMap) {
152 if (auto EC = DW.writeArray(Blocks))
153 return EC;
154 }
155
Zachary Turnerc504ae32017-05-03 15:58:37 +0000156 auto ExpectedSN = getNamedStreamIndex("/names");
157 if (!ExpectedSN)
158 return ExpectedSN.takeError();
Zachary Turner760ad4d2017-01-20 22:42:09 +0000159
Zachary Turnerc504ae32017-05-03 15:58:37 +0000160 auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
161 *ExpectedSN);
Zachary Turner120faca2017-02-27 22:11:43 +0000162 BinaryStreamWriter NSWriter(*NS);
Zachary Turner760ad4d2017-01-20 22:42:09 +0000163 if (auto EC = Strings.commit(NSWriter))
164 return EC;
165
Zachary Turnerd66889c2016-07-28 19:12:28 +0000166 if (Info) {
167 if (auto EC = Info->commit(Layout, Buffer))
168 return EC;
169 }
170
171 if (Dbi) {
172 if (auto EC = Dbi->commit(Layout, Buffer))
173 return EC;
174 }
175
Zachary Turnerc6d54da2016-09-09 17:46:17 +0000176 if (Tpi) {
177 if (auto EC = Tpi->commit(Layout, Buffer))
178 return EC;
179 }
180
Zachary Turnerde9ba152016-09-15 18:22:31 +0000181 if (Ipi) {
182 if (auto EC = Ipi->commit(Layout, Buffer))
183 return EC;
184 }
185
Zachary Turnerd66889c2016-07-28 19:12:28 +0000186 return Buffer.commit();
Rui Ueyamafc22cef2016-09-30 20:34:44 +0000187}