Line data Source code
1 : //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
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/Native/DbiStream.h"
11 : #include "llvm/ADT/StringRef.h"
12 : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
13 : #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
14 : #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
15 : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
16 : #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
17 : #include "llvm/DebugInfo/PDB/Native/RawError.h"
18 : #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
19 : #include "llvm/DebugInfo/PDB/PDBTypes.h"
20 : #include "llvm/Object/COFF.h"
21 : #include "llvm/Support/BinaryStreamArray.h"
22 : #include "llvm/Support/BinaryStreamReader.h"
23 : #include "llvm/Support/Error.h"
24 : #include <algorithm>
25 : #include <cstddef>
26 : #include <cstdint>
27 :
28 : using namespace llvm;
29 : using namespace llvm::codeview;
30 : using namespace llvm::msf;
31 : using namespace llvm::pdb;
32 : using namespace llvm::support;
33 :
34 : template <typename ContribType>
35 103 : static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
36 : BinaryStreamReader &Reader) {
37 103 : if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
38 : return make_error<RawError>(
39 : raw_error_code::corrupt_file,
40 : "Invalid number of bytes of section contributions");
41 :
42 103 : uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
43 206 : if (auto EC = Reader.readArray(Output, Count))
44 : return EC;
45 : return Error::success();
46 : }
47 0 :
48 : DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
49 0 : : Stream(std::move(Stream)), Header(nullptr) {}
50 :
51 : DbiStream::~DbiStream() = default;
52 :
53 : Error DbiStream::reload(PDBFile *Pdb) {
54 0 : BinaryStreamReader Reader(*Stream);
55 0 :
56 : if (Stream->getLength() < sizeof(DbiStreamHeader))
57 : return make_error<RawError>(raw_error_code::corrupt_file,
58 : "DBI Stream does not contain a header.");
59 103 : if (auto EC = Reader.readObject(Header))
60 : return make_error<RawError>(raw_error_code::corrupt_file,
61 103 : "DBI Stream does not contain a header.");
62 :
63 : if (Header->VersionSignature != -1)
64 : return make_error<RawError>(raw_error_code::corrupt_file,
65 : "Invalid DBI version signature.");
66 103 :
67 206 : // Require at least version 7, which should be present in all PDBs
68 : // produced in the last decade and allows us to avoid having to
69 : // special case all kinds of complicated arcane formats.
70 : if (Header->VersionHeader < PdbDbiV70)
71 : return make_error<RawError>(raw_error_code::feature_unsupported,
72 127 : "Unsupported DBI version.");
73 127 :
74 : if (Stream->getLength() !=
75 : sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
76 : Header->SecContrSubstreamSize + Header->SectionMapSize +
77 127 : Header->FileInfoSize + Header->TypeServerSize +
78 127 : Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
79 : return make_error<RawError>(raw_error_code::corrupt_file,
80 127 : "DBI Length does not equal sum of substreams.");
81 :
82 : // Only certain substreams are guaranteed to be aligned. Validate
83 244 : // them here.
84 : if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
85 : return make_error<RawError>(raw_error_code::corrupt_file,
86 : "DBI MODI substream not aligned.");
87 244 : if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
88 : return make_error<RawError>(
89 : raw_error_code::corrupt_file,
90 : "DBI section contribution substream not aligned.");
91 : if (Header->SectionMapSize % sizeof(uint32_t) != 0)
92 : return make_error<RawError>(raw_error_code::corrupt_file,
93 : "DBI section map substream not aligned.");
94 122 : if (Header->FileInfoSize % sizeof(uint32_t) != 0)
95 : return make_error<RawError>(raw_error_code::corrupt_file,
96 : "DBI file info substream not aligned.");
97 : if (Header->TypeServerSize % sizeof(uint32_t) != 0)
98 122 : return make_error<RawError>(raw_error_code::corrupt_file,
99 244 : "DBI type server substream not aligned.");
100 244 :
101 244 : if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
102 244 : return EC;
103 :
104 : if (auto EC = Reader.readSubstream(SecContrSubstream,
105 : Header->SecContrSubstreamSize))
106 : return EC;
107 : if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
108 122 : return EC;
109 : if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
110 : return EC;
111 122 : if (auto EC =
112 : Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
113 : return EC;
114 : if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
115 122 : return EC;
116 : if (auto EC = Reader.readArray(
117 : DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
118 122 : return EC;
119 :
120 : if (auto EC = Modules.initialize(ModiSubstream.StreamData,
121 122 : FileInfoSubstream.StreamData))
122 : return EC;
123 :
124 : if (auto EC = initializeSectionContributionData())
125 244 : return EC;
126 : if (auto EC = initializeSectionHeadersData(Pdb))
127 : return EC;
128 122 : if (auto EC = initializeSectionMapData())
129 244 : return EC;
130 : if (auto EC = initializeFpoRecords(Pdb))
131 366 : return EC;
132 :
133 366 : if (Reader.bytesRemaining() > 0)
134 : return make_error<RawError>(raw_error_code::corrupt_file,
135 122 : "Found unexpected bytes in DBI Stream.");
136 244 :
137 : if (!ECSubstream.empty()) {
138 366 : BinaryStreamReader ECReader(ECSubstream.StreamData);
139 : if (auto EC = ECNames.reload(ECReader))
140 122 : return EC;
141 244 : }
142 :
143 : return Error::success();
144 122 : }
145 366 :
146 : PdbRaw_DbiVer DbiStream::getDbiVersion() const {
147 : uint32_t Value = Header->VersionHeader;
148 244 : return static_cast<PdbRaw_DbiVer>(Value);
149 : }
150 244 :
151 : uint32_t DbiStream::getAge() const { return Header->Age; }
152 244 :
153 : uint16_t DbiStream::getPublicSymbolStreamIndex() const {
154 244 : return Header->PublicSymbolStreamIndex;
155 : }
156 :
157 122 : uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
158 : return Header->GlobalSymbolStreamIndex;
159 : }
160 :
161 122 : uint16_t DbiStream::getFlags() const { return Header->Flags; }
162 122 :
163 244 : bool DbiStream::isIncrementallyLinked() const {
164 : return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
165 : }
166 :
167 : bool DbiStream::hasCTypes() const {
168 : return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
169 : }
170 14 :
171 14 : bool DbiStream::isStripped() const {
172 14 : return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
173 : }
174 :
175 28 : uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
176 :
177 109 : uint16_t DbiStream::getBuildMajorVersion() const {
178 218 : return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
179 : DbiBuildNo::BuildMajorShift;
180 : }
181 141 :
182 282 : uint16_t DbiStream::getBuildMinorVersion() const {
183 : return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
184 : DbiBuildNo::BuildMinorShift;
185 28 : }
186 :
187 4 : uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
188 8 :
189 : uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
190 :
191 12 : uint32_t DbiStream::getSymRecordStreamIndex() const {
192 24 : return Header->SymRecordStreamIndex;
193 : }
194 :
195 12 : PDB_Machine DbiStream::getMachineType() const {
196 24 : uint16_t Machine = Header->MachineType;
197 : return static_cast<PDB_Machine>(Machine);
198 : }
199 28 :
200 : FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
201 0 : return SectionHeaders;
202 0 : }
203 0 :
204 : FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
205 : return FpoRecords;
206 0 : }
207 0 :
208 0 : const DbiModuleList &DbiStream::modules() const { return Modules; }
209 :
210 : FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
211 28 : return SectionMap;
212 : }
213 28 :
214 : void DbiStream::visitSectionContributions(
215 107 : ISectionContribVisitor &Visitor) const {
216 214 : if (!SectionContribs.empty()) {
217 : assert(SectionContribVersion == DbiSecContribVer60);
218 : for (auto &SC : SectionContribs)
219 14 : Visitor.visit(SC);
220 14 : } else if (!SectionContribs2.empty()) {
221 14 : assert(SectionContribVersion == DbiSecContribV2);
222 : for (auto &SC : SectionContribs2)
223 : Visitor.visit(SC);
224 0 : }
225 0 : }
226 :
227 : Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
228 0 : return ECNames.getStringForID(NI);
229 0 : }
230 :
231 : Error DbiStream::initializeSectionContributionData() {
232 1183 : if (SecContrSubstream.empty())
233 : return Error::success();
234 2 :
235 2 : BinaryStreamReader SCReader(SecContrSubstream.StreamData);
236 : if (auto EC = SCReader.readEnum(SectionContribVersion))
237 : return EC;
238 3 :
239 : if (SectionContribVersion == DbiSecContribVer60)
240 3 : return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
241 : if (SectionContribVersion == DbiSecContribV2)
242 34 : return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
243 28 :
244 0 : return make_error<RawError>(raw_error_code::feature_unsupported,
245 : "Unsupported DBI Section Contribution version");
246 0 : }
247 0 :
248 : // Initializes this->SectionHeaders.
249 3 : Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
250 : if (!Pdb)
251 220 : return Error::success();
252 220 :
253 : if (DbgStreams.size() == 0)
254 : return Error::success();
255 122 :
256 122 : uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
257 : if (StreamNum == kInvalidStreamIndex)
258 : return Error::success();
259 103 :
260 206 : if (StreamNum >= Pdb->getNumStreams())
261 : return make_error<RawError>(raw_error_code::no_stream);
262 :
263 103 : auto SHS = MappedBlockStream::createIndexedStream(
264 103 : Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
265 0 :
266 0 : size_t StreamLen = SHS->getLength();
267 : if (StreamLen % sizeof(object::coff_section))
268 : return make_error<RawError>(raw_error_code::corrupt_file,
269 : "Corrupted section header stream.");
270 :
271 : size_t NumSections = StreamLen / sizeof(object::coff_section);
272 : BinaryStreamReader Reader(*SHS);
273 122 : if (auto EC = Reader.readArray(SectionHeaders, NumSections))
274 122 : return make_error<RawError>(raw_error_code::corrupt_file,
275 : "Could not read a bitmap.");
276 :
277 122 : SectionHeaderStream = std::move(SHS);
278 : return Error::success();
279 : }
280 122 :
281 122 : // Initializes this->Fpos.
282 : Error DbiStream::initializeFpoRecords(PDBFile *Pdb) {
283 : if (!Pdb)
284 103 : return Error::success();
285 :
286 : if (DbgStreams.size() == 0)
287 : return Error::success();
288 206 :
289 : uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
290 103 :
291 103 : // This means there is no FPO data.
292 : if (StreamNum == kInvalidStreamIndex)
293 : return Error::success();
294 :
295 103 : if (StreamNum >= Pdb->getNumStreams())
296 103 : return make_error<RawError>(raw_error_code::no_stream);
297 206 :
298 : auto FS = MappedBlockStream::createIndexedStream(
299 : Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
300 :
301 : size_t StreamLen = FS->getLength();
302 : if (StreamLen % sizeof(object::FpoData))
303 : return make_error<RawError>(raw_error_code::corrupt_file,
304 : "Corrupted New FPO stream.");
305 :
306 122 : size_t NumRecords = StreamLen / sizeof(object::FpoData);
307 122 : BinaryStreamReader Reader(*FS);
308 : if (auto EC = Reader.readArray(FpoRecords, NumRecords))
309 : return make_error<RawError>(raw_error_code::corrupt_file,
310 122 : "Corrupted New FPO stream.");
311 : FpoStream = std::move(FS);
312 : return Error::success();
313 122 : }
314 :
315 : BinarySubstreamRef DbiStream::getSectionContributionData() const {
316 122 : return SecContrSubstream;
317 : }
318 :
319 66 : BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
320 : return SecMapSubstream;
321 : }
322 :
323 132 : BinarySubstreamRef DbiStream::getModiSubstreamData() const {
324 : return ModiSubstream;
325 66 : }
326 66 :
327 : BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
328 : return FileInfoSubstream;
329 : }
330 66 :
331 66 : BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
332 132 : return TypeServerMapSubstream;
333 : }
334 :
335 : BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
336 :
337 : Error DbiStream::initializeSectionMapData() {
338 : if (SecMapSubstream.empty())
339 1 : return Error::success();
340 1 :
341 : BinaryStreamReader SMReader(SecMapSubstream.StreamData);
342 : const SecMapHeader *Header;
343 1 : if (auto EC = SMReader.readObject(Header))
344 1 : return EC;
345 : if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
346 : return EC;
347 1 : return Error::success();
348 1 : }
349 :
350 : uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
351 1 : uint16_t T = static_cast<uint16_t>(Type);
352 1 : if (T >= DbgStreams.size())
353 : return kInvalidStreamIndex;
354 : return DbgStreams[T];
355 1 : }
|