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