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