Line data Source code
1 : //===- 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 :
12 : #include "llvm/ADT/BitVector.h"
13 :
14 : #include "llvm/DebugInfo/MSF/MSFBuilder.h"
15 : #include "llvm/DebugInfo/MSF/StreamInterface.h"
16 : #include "llvm/DebugInfo/MSF/StreamWriter.h"
17 : #include "llvm/DebugInfo/PDB/GenericError.h"
18 : #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"
23 : #include "llvm/DebugInfo/PDB/Raw/StringTableBuilder.h"
24 : #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
25 : #include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
26 :
27 : using namespace llvm;
28 : using namespace llvm::codeview;
29 : using namespace llvm::msf;
30 : using namespace llvm::pdb;
31 : using namespace llvm::support;
32 :
33 4 : PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
34 28 : : Allocator(Allocator) {}
35 :
36 4 : Error PDBFileBuilder::initialize(uint32_t BlockSize) {
37 8 : auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
38 4 : if (!ExpectedMsf)
39 0 : return ExpectedMsf.takeError();
40 8 : Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
41 12 : return Error::success();
42 : }
43 :
44 40 : MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
45 :
46 4 : InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
47 8 : if (!Info)
48 12 : Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
49 8 : return *Info;
50 : }
51 :
52 3 : DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
53 6 : if (!Dbi)
54 9 : Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
55 6 : return *Dbi;
56 : }
57 :
58 4 : TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
59 8 : if (!Tpi)
60 12 : Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
61 8 : return *Tpi;
62 : }
63 :
64 2 : TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
65 4 : if (!Ipi)
66 6 : Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
67 4 : return *Ipi;
68 : }
69 :
70 1 : StringTableBuilder &PDBFileBuilder::getStringTableBuilder() { return Strings; }
71 :
72 12 : Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
73 36 : auto ExpectedStream = Msf->addStream(Size);
74 12 : if (!ExpectedStream)
75 0 : return ExpectedStream.takeError();
76 12 : NamedStreams.set(Name, *ExpectedStream);
77 36 : return Error::success();
78 : }
79 :
80 4 : Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
81 4 : uint32_t StringTableSize = Strings.finalize();
82 :
83 8 : if (auto EC = addNamedStream("/names", StringTableSize))
84 0 : return std::move(EC);
85 12 : if (auto EC = addNamedStream("/LinkInfo", 0))
86 0 : return std::move(EC);
87 12 : if (auto EC = addNamedStream("/src/headerblock", 0))
88 0 : return std::move(EC);
89 :
90 8 : if (Info) {
91 16 : if (auto EC = Info->finalizeMsfLayout())
92 0 : return std::move(EC);
93 : }
94 8 : if (Dbi) {
95 12 : if (auto EC = Dbi->finalizeMsfLayout())
96 0 : return std::move(EC);
97 : }
98 8 : if (Tpi) {
99 16 : if (auto EC = Tpi->finalizeMsfLayout())
100 0 : return std::move(EC);
101 : }
102 8 : if (Ipi) {
103 8 : if (auto EC = Ipi->finalizeMsfLayout())
104 0 : return std::move(EC);
105 : }
106 :
107 8 : return Msf->build();
108 : }
109 :
110 4 : Error PDBFileBuilder::commit(StringRef Filename) {
111 8 : auto ExpectedLayout = finalizeMsfLayout();
112 4 : if (!ExpectedLayout)
113 0 : return ExpectedLayout.takeError();
114 4 : auto &Layout = *ExpectedLayout;
115 :
116 12 : uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
117 4 : auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
118 4 : if (OutFileOrError.getError())
119 : return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
120 0 : Filename);
121 8 : FileBufferByteStream Buffer(std::move(*OutFileOrError));
122 4 : StreamWriter Writer(Buffer);
123 :
124 16 : if (auto EC = Writer.writeObject(*Layout.SB))
125 0 : return EC;
126 : uint32_t BlockMapOffset =
127 16 : msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
128 8 : Writer.setOffset(BlockMapOffset);
129 12 : if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
130 0 : return EC;
131 :
132 : auto DirStream =
133 4 : WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
134 8 : StreamWriter DW(*DirStream);
135 4 : if (auto EC =
136 8 : DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size())))
137 0 : return EC;
138 :
139 12 : if (auto EC = DW.writeArray(Layout.StreamSizes))
140 0 : return EC;
141 :
142 50 : for (const auto &Blocks : Layout.StreamMap) {
143 102 : if (auto EC = DW.writeArray(Blocks))
144 0 : return EC;
145 : }
146 :
147 4 : uint32_t StringTableStreamNo = 0;
148 4 : if (!NamedStreams.get("/names", StringTableStreamNo))
149 0 : return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
150 :
151 : auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
152 4 : StringTableStreamNo);
153 8 : StreamWriter NSWriter(*NS);
154 12 : if (auto EC = Strings.commit(NSWriter))
155 0 : return EC;
156 :
157 8 : if (Info) {
158 16 : if (auto EC = Info->commit(Layout, Buffer))
159 0 : return EC;
160 : }
161 :
162 8 : if (Dbi) {
163 12 : if (auto EC = Dbi->commit(Layout, Buffer))
164 0 : return EC;
165 : }
166 :
167 8 : if (Tpi) {
168 16 : if (auto EC = Tpi->commit(Layout, Buffer))
169 0 : return EC;
170 : }
171 :
172 8 : if (Ipi) {
173 8 : if (auto EC = Ipi->commit(Layout, Buffer))
174 0 : return EC;
175 : }
176 :
177 : return Buffer.commit();
178 : }
|